Merge remote-tracking branch 'upstream/develop-rando' into soulcalibur
This commit is contained in:
@@ -147,11 +147,6 @@ typedef struct {
|
||||
/* 0x24 */ s32 tempCollectFlags;
|
||||
} FaroresWindData; // size = 0x28
|
||||
|
||||
typedef struct {
|
||||
RandomizerCheck check;
|
||||
RandomizerGetData get;
|
||||
} ItemLocationRando;
|
||||
|
||||
typedef struct {
|
||||
RandomizerCheck check;
|
||||
RandomizerCheck hintedCheck;
|
||||
@@ -161,11 +156,6 @@ typedef struct {
|
||||
char hintText[200];
|
||||
} HintLocationRando;
|
||||
|
||||
typedef struct {
|
||||
RandomizerSettingKey key;
|
||||
u8 value;
|
||||
} RandoSetting;
|
||||
|
||||
typedef struct {
|
||||
/* 0x0000 */ s32 entranceIndex; // start of `save` substruct, originally called "memory"
|
||||
/* 0x0004 */ s32 linkAge; // 0: Adult; 1: Child (see enum `LinkAge`)
|
||||
@@ -286,7 +276,6 @@ typedef struct {
|
||||
/* */ uint8_t questId;
|
||||
/* */ uint32_t isBossRushPaused;
|
||||
/* */ uint8_t bossRushOptions[BOSSRUSH_OPTIONS_AMOUNT];
|
||||
/* */ u8 mqDungeonCount;
|
||||
/* */ u8 pendingIceTrapCount;
|
||||
/* */ SohStats sohStats;
|
||||
/* */ FaroresWindData backupFW;
|
||||
@@ -294,33 +283,6 @@ typedef struct {
|
||||
// #endregion
|
||||
// #region SOH [Randomizer]
|
||||
// Upstream TODO: Move these to their own struct or name to more obviously specific to Randomizer
|
||||
/* */ RandoSetting randoSettings[300];
|
||||
/* */ ItemLocationRando itemLocations[RC_MAX];
|
||||
/* */ HintLocationRando hintLocations[50];
|
||||
/* */ EntranceOverride entranceOverrides[ENTRANCE_OVERRIDES_MAX_COUNT];
|
||||
/* */ char childAltarText[250];
|
||||
/* */ char adultAltarText[750];
|
||||
/* */ RandomizerCheck rewardCheck[9];
|
||||
/* */ char ganonHintText[300];
|
||||
/* */ char gregHintText[250];
|
||||
/* */ char ganonText[250];
|
||||
/* */ char dampeText[150];
|
||||
/* */ char sheikText[200];
|
||||
/* */ char sariaText[150];
|
||||
/* */ char warpMinuetText[100];
|
||||
/* */ char warpBoleroText[100];
|
||||
/* */ char warpSerenadeText[100];
|
||||
/* */ char warpRequiemText[100];
|
||||
/* */ char warpNocturneText[100];
|
||||
/* */ char warpPreludeText[100];
|
||||
/* */ RandomizerCheck masterSwordHintCheck;
|
||||
/* */ RandomizerCheck lightArrowHintCheck;
|
||||
/* */ RandomizerCheck sariaCheck;
|
||||
/* */ RandomizerCheck gregCheck;
|
||||
/* */ RandomizerCheck dampeCheck;
|
||||
/* */ char inputSeed[1024];
|
||||
/* */ u32 finalSeed;
|
||||
/* */ u8 seedIcons[5];
|
||||
/* */ u16 randomizerInf[10];
|
||||
/* */ u16 adultTradeItems;
|
||||
/* */ u8 triforcePiecesCollected;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
#include "soh/Enhancements/randomizer/3drando/random.hpp"
|
||||
#include "soh/Enhancements/randomizer/context.h"
|
||||
#include "soh/Enhancements/enhancementTypes.h"
|
||||
#include "variables.h"
|
||||
|
||||
@@ -234,7 +235,7 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
|
||||
|
||||
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
|
||||
if (CVarGetInteger("gRandomizedEnemies", ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
|
||||
uint32_t finalSeed = seed + (IS_RANDO ? gSaveContext.finalSeed : gSaveContext.sohStats.fileCreatedAt);
|
||||
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed() : gSaveContext.sohStats.fileCreatedAt);
|
||||
Random_Init(finalSeed);
|
||||
}
|
||||
|
||||
|
||||
@@ -604,7 +604,8 @@ void UpdateMirrorModeState(int32_t sceneNum) {
|
||||
(sceneNum == SCENE_GANON_BOSS);
|
||||
|
||||
if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) {
|
||||
uint32_t seed = sceneNum + (IS_RANDO ? gSaveContext.finalSeed : gSaveContext.sohStats.fileCreatedAt);
|
||||
uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed()
|
||||
: gSaveContext.sohStats.fileCreatedAt);
|
||||
Random_Init(seed);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,682 +0,0 @@
|
||||
#include "dungeon.hpp"
|
||||
|
||||
#include "category.hpp"
|
||||
#include "pool_functions.hpp"
|
||||
#include "../context.h"
|
||||
#include "../static_data.h"
|
||||
|
||||
namespace Dungeon {
|
||||
|
||||
DungeonInfo::DungeonInfo(std::string name_, RandomizerHintTextKey hintKey_, RandomizerGet map_, RandomizerGet compass_,
|
||||
RandomizerGet smallKey_, RandomizerGet keyRing_, RandomizerGet bossKey_,
|
||||
uint8_t vanillaKeyCount_, uint8_t mqKeyCount_, std::vector<RandomizerCheck> vanillaLocations_,
|
||||
std::vector<RandomizerCheck> mqLocations_, std::vector<RandomizerCheck> sharedLocations_,
|
||||
std::vector<RandomizerCheck> bossRoomLocations_)
|
||||
: name(std::move(name_)), hintKey(hintKey_), map(map_), compass(compass_), smallKey(smallKey_), keyRing(keyRing_),
|
||||
bossKey(bossKey_), vanillaKeyCount(vanillaKeyCount_), mqKeyCount(mqKeyCount_),
|
||||
vanillaLocations(std::move(vanillaLocations_)), mqLocations(std::move(mqLocations_)),
|
||||
sharedLocations(std::move(sharedLocations_)), bossRoomLocations(std::move(bossRoomLocations_)) {
|
||||
}
|
||||
|
||||
DungeonInfo::~DungeonInfo() = default;
|
||||
|
||||
RandomizerHintTextKey DungeonInfo::GetHintKey() const {
|
||||
return hintKey;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetSmallKey() const {
|
||||
return smallKey;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetKeyRing() const {
|
||||
return keyRing;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetMap() const {
|
||||
return map;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetCompass() const {
|
||||
return compass;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetBossKey() const {
|
||||
return bossKey;
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaMap() {
|
||||
if (map == RG_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto mapLocation = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) {
|
||||
return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cVanillaMap);
|
||||
})[0];
|
||||
Rando::Context::GetInstance()->PlaceItemInLocation(mapLocation, map);
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaCompass() {
|
||||
if (compass == RG_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto compassLocation = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) {
|
||||
return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cVanillaCompass);
|
||||
})[0];
|
||||
Rando::Context::GetInstance()->PlaceItemInLocation(compassLocation, compass);
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaBossKey() {
|
||||
if (bossKey == RG_NONE || bossKey == RG_GANONS_CASTLE_BOSS_KEY) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto bossKeyLocation = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) {
|
||||
return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cVanillaBossKey);
|
||||
})[0];
|
||||
Rando::Context::GetInstance()->PlaceItemInLocation(bossKeyLocation, bossKey);
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaSmallKeys() {
|
||||
if (smallKey == RG_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto smallKeyLocations = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) {
|
||||
return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cVanillaSmallKey);
|
||||
});
|
||||
for (auto location : smallKeyLocations) {
|
||||
Rando::Context::GetInstance()->PlaceItemInLocation(location, smallKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla)
|
||||
std::vector<RandomizerCheck> DungeonInfo::GetDungeonLocations() const {
|
||||
auto locations = masterQuest ? mqLocations : vanillaLocations;
|
||||
AddElementsToPool(locations, sharedLocations);
|
||||
AddElementsToPool(locations, bossRoomLocations);
|
||||
return locations;
|
||||
}
|
||||
|
||||
// Gets all dungeon locations (MQ + Vanilla)
|
||||
std::vector<RandomizerCheck> DungeonInfo::GetEveryLocation() const {
|
||||
auto locations = vanillaLocations;
|
||||
AddElementsToPool(locations, mqLocations);
|
||||
AddElementsToPool(locations, sharedLocations);
|
||||
AddElementsToPool(locations, bossRoomLocations);
|
||||
return locations;
|
||||
}
|
||||
|
||||
DungeonInfo DekuTree =
|
||||
DungeonInfo("Deku Tree", RHT_DEKU_TREE, RG_DEKU_TREE_MAP, RG_DEKU_TREE_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_DEKU_TREE_MAP_CHEST,
|
||||
RC_DEKU_TREE_COMPASS_CHEST,
|
||||
RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST,
|
||||
RC_DEKU_TREE_BASEMENT_CHEST,
|
||||
RC_DEKU_TREE_SLINGSHOT_CHEST,
|
||||
RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST,
|
||||
RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM,
|
||||
RC_DEKU_TREE_GS_BASEMENT_GATE,
|
||||
RC_DEKU_TREE_GS_BASEMENT_VINES,
|
||||
RC_DEKU_TREE_GS_COMPASS_ROOM,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_DEKU_TREE_MQ_MAP_CHEST,
|
||||
RC_DEKU_TREE_MQ_COMPASS_CHEST,
|
||||
RC_DEKU_TREE_MQ_SLINGSHOT_CHEST,
|
||||
RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST,
|
||||
RC_DEKU_TREE_MQ_BASEMENT_CHEST,
|
||||
RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST,
|
||||
RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST,
|
||||
RC_DEKU_TREE_MQ_DEKU_SCRUB,
|
||||
RC_DEKU_TREE_MQ_GS_LOBBY,
|
||||
RC_DEKU_TREE_MQ_GS_COMPASS_ROOM,
|
||||
RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM,
|
||||
RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_DEKU_TREE_QUEEN_GOHMA_HEART,
|
||||
RC_QUEEN_GOHMA,
|
||||
});
|
||||
|
||||
DungeonInfo DodongosCavern = DungeonInfo("Dodongo's Cavern", RHT_DODONGOS_CAVERN, RG_DODONGOS_CAVERN_MAP,
|
||||
RG_DODONGOS_CAVERN_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_DODONGOS_CAVERN_MAP_CHEST,
|
||||
RC_DODONGOS_CAVERN_COMPASS_CHEST,
|
||||
RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST,
|
||||
RC_DODONGOS_CAVERN_BOMB_BAG_CHEST,
|
||||
RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST,
|
||||
RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY,
|
||||
RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS,
|
||||
RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT,
|
||||
RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT,
|
||||
RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS,
|
||||
RC_DODONGOS_CAVERN_GS_SCARECROW,
|
||||
RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS,
|
||||
RC_DODONGOS_CAVERN_GS_BACK_ROOM,
|
||||
RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_DODONGOS_CAVERN_MQ_MAP_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR,
|
||||
RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT,
|
||||
RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE,
|
||||
RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS,
|
||||
RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM,
|
||||
RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM,
|
||||
RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM,
|
||||
RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM,
|
||||
RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST,
|
||||
RC_DODONGOS_CAVERN_KING_DODONGO_HEART,
|
||||
RC_KING_DODONGO,
|
||||
});
|
||||
|
||||
DungeonInfo JabuJabusBelly = DungeonInfo("Jabu Jabu's Belly", RHT_JABU_JABUS_BELLY, RG_JABU_JABUS_BELLY_MAP,
|
||||
RG_JABU_JABUS_BELLY_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_JABU_JABUS_BELLY_MAP_CHEST,
|
||||
RC_JABU_JABUS_BELLY_COMPASS_CHEST,
|
||||
RC_JABU_JABUS_BELLY_BOOMERANG_CHEST,
|
||||
RC_JABU_JABUS_BELLY_DEKU_SCRUB,
|
||||
RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER,
|
||||
RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER,
|
||||
RC_JABU_JABUS_BELLY_GS_NEAR_BOSS,
|
||||
RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_MAP_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_COW,
|
||||
RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM,
|
||||
RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM,
|
||||
RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM,
|
||||
RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_JABU_JABUS_BELLY_BARINADE_HEART,
|
||||
RC_BARINADE,
|
||||
});
|
||||
|
||||
DungeonInfo ForestTemple =
|
||||
DungeonInfo("Forest Temple", RHT_FOREST_TEMPLE, RG_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_COMPASS,
|
||||
RG_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_BOSS_KEY, 5, 6,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_FOREST_TEMPLE_FIRST_ROOM_CHEST,
|
||||
RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST,
|
||||
RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST,
|
||||
RC_FOREST_TEMPLE_MAP_CHEST,
|
||||
RC_FOREST_TEMPLE_WELL_CHEST,
|
||||
RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST,
|
||||
RC_FOREST_TEMPLE_EYE_SWITCH_CHEST,
|
||||
RC_FOREST_TEMPLE_BOSS_KEY_CHEST,
|
||||
RC_FOREST_TEMPLE_FLOORMASTER_CHEST,
|
||||
RC_FOREST_TEMPLE_BOW_CHEST,
|
||||
RC_FOREST_TEMPLE_RED_POE_CHEST,
|
||||
RC_FOREST_TEMPLE_BLUE_POE_CHEST,
|
||||
RC_FOREST_TEMPLE_BASEMENT_CHEST,
|
||||
RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD,
|
||||
RC_FOREST_TEMPLE_GS_FIRST_ROOM,
|
||||
RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD,
|
||||
RC_FOREST_TEMPLE_GS_LOBBY,
|
||||
RC_FOREST_TEMPLE_GS_BASEMENT,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_BOW_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_WELL_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_MAP_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_COMPASS_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_REDEAD_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY,
|
||||
RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM,
|
||||
RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD,
|
||||
RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD,
|
||||
RC_FOREST_TEMPLE_MQ_GS_WELL,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_FOREST_TEMPLE_PHANTOM_GANON_HEART,
|
||||
RC_PHANTOM_GANON,
|
||||
});
|
||||
|
||||
DungeonInfo FireTemple = DungeonInfo("Fire Temple", RHT_FIRE_TEMPLE, RG_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_COMPASS,
|
||||
RG_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_BOSS_KEY, 8, 5,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_FIRE_TEMPLE_NEAR_BOSS_CHEST,
|
||||
RC_FIRE_TEMPLE_FLARE_DANCER_CHEST,
|
||||
RC_FIRE_TEMPLE_BOSS_KEY_CHEST,
|
||||
RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST,
|
||||
RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST,
|
||||
RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST,
|
||||
RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST,
|
||||
RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST,
|
||||
RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST,
|
||||
RC_FIRE_TEMPLE_SCARECROW_CHEST,
|
||||
RC_FIRE_TEMPLE_MAP_CHEST,
|
||||
RC_FIRE_TEMPLE_COMPASS_CHEST,
|
||||
RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST,
|
||||
RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST,
|
||||
RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM,
|
||||
RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP,
|
||||
RC_FIRE_TEMPLE_GS_BOULDER_MAZE,
|
||||
RC_FIRE_TEMPLE_GS_SCARECROW_TOP,
|
||||
RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_COMPASS_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE,
|
||||
RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_MAP_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY,
|
||||
RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE,
|
||||
RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER,
|
||||
RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR,
|
||||
RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM,
|
||||
RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boos Room Locations
|
||||
RC_FIRE_TEMPLE_VOLVAGIA_HEART,
|
||||
RC_VOLVAGIA,
|
||||
});
|
||||
|
||||
DungeonInfo WaterTemple =
|
||||
DungeonInfo("Water Temple", RHT_WATER_TEMPLE, RG_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_COMPASS,
|
||||
RG_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_BOSS_KEY, 6, 2,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_WATER_TEMPLE_MAP_CHEST,
|
||||
RC_WATER_TEMPLE_COMPASS_CHEST,
|
||||
RC_WATER_TEMPLE_TORCHES_CHEST,
|
||||
RC_WATER_TEMPLE_DRAGON_CHEST,
|
||||
RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST,
|
||||
RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST,
|
||||
RC_WATER_TEMPLE_CRACKED_WALL_CHEST,
|
||||
RC_WATER_TEMPLE_BOSS_KEY_CHEST,
|
||||
RC_WATER_TEMPLE_LONGSHOT_CHEST,
|
||||
RC_WATER_TEMPLE_RIVER_CHEST,
|
||||
RC_WATER_TEMPLE_GS_BEHIND_GATE,
|
||||
RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM,
|
||||
RC_WATER_TEMPLE_GS_CENTRAL_PILLAR,
|
||||
RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST,
|
||||
RC_WATER_TEMPLE_GS_RIVER,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST,
|
||||
RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST,
|
||||
RC_WATER_TEMPLE_MQ_COMPASS_CHEST,
|
||||
RC_WATER_TEMPLE_MQ_MAP_CHEST,
|
||||
RC_WATER_TEMPLE_MQ_FREESTANDING_KEY,
|
||||
RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH,
|
||||
RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA,
|
||||
RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY,
|
||||
RC_WATER_TEMPLE_MQ_GS_RIVER,
|
||||
RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_WATER_TEMPLE_MORPHA_HEART,
|
||||
RC_MORPHA,
|
||||
});
|
||||
|
||||
DungeonInfo SpiritTemple =
|
||||
DungeonInfo("Spirit Temple", RHT_SPIRIT_TEMPLE, RG_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_COMPASS,
|
||||
RG_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_BOSS_KEY, 5, 7,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST,
|
||||
RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST,
|
||||
RC_SPIRIT_TEMPLE_COMPASS_CHEST,
|
||||
RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MAP_CHEST,
|
||||
RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST,
|
||||
RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST,
|
||||
RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST,
|
||||
RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST,
|
||||
RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST,
|
||||
RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST,
|
||||
RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST,
|
||||
RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST,
|
||||
RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST,
|
||||
RC_SPIRIT_TEMPLE_TOPMOST_CHEST,
|
||||
RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM,
|
||||
RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM,
|
||||
RC_SPIRIT_TEMPLE_GS_LOBBY,
|
||||
RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM,
|
||||
RC_SPIRIT_TEMPLE_GS_METAL_FENCE,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_MAP_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM,
|
||||
RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM,
|
||||
RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH,
|
||||
RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM,
|
||||
},
|
||||
{
|
||||
// Shared Locations
|
||||
RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST,
|
||||
},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_SPIRIT_TEMPLE_TWINROVA_HEART,
|
||||
RC_TWINROVA,
|
||||
});
|
||||
|
||||
DungeonInfo ShadowTemple =
|
||||
DungeonInfo("Shadow Temple", RHT_SHADOW_TEMPLE, RG_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_COMPASS,
|
||||
RG_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_BOSS_KEY, 5, 6,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_SHADOW_TEMPLE_MAP_CHEST,
|
||||
RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST,
|
||||
RC_SHADOW_TEMPLE_COMPASS_CHEST,
|
||||
RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST,
|
||||
RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST,
|
||||
RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST,
|
||||
RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST,
|
||||
RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST,
|
||||
RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST,
|
||||
RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST,
|
||||
RC_SHADOW_TEMPLE_WIND_HINT_CHEST,
|
||||
RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST,
|
||||
RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST,
|
||||
RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST,
|
||||
RC_SHADOW_TEMPLE_BOSS_KEY_CHEST,
|
||||
RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST,
|
||||
RC_SHADOW_TEMPLE_FREESTANDING_KEY,
|
||||
RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT,
|
||||
RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM,
|
||||
RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT,
|
||||
RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM,
|
||||
RC_SHADOW_TEMPLE_GS_NEAR_SHIP,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_MAP_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY,
|
||||
RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM,
|
||||
RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM,
|
||||
RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND,
|
||||
RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP,
|
||||
RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_SHADOW_TEMPLE_BONGO_BONGO_HEART,
|
||||
RC_BONGO_BONGO,
|
||||
});
|
||||
|
||||
DungeonInfo BottomOfTheWell =
|
||||
DungeonInfo("Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, RG_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_COMPASS,
|
||||
RG_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_KEY_RING, RG_NONE, 3, 2,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_MAP_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY,
|
||||
RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE,
|
||||
RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM,
|
||||
RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM,
|
||||
},
|
||||
{}, {});
|
||||
|
||||
DungeonInfo IceCavern =
|
||||
DungeonInfo("Ice Cavern", RHT_ICE_CAVERN, RG_ICE_CAVERN_MAP, RG_ICE_CAVERN_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_ICE_CAVERN_MAP_CHEST,
|
||||
RC_ICE_CAVERN_COMPASS_CHEST,
|
||||
RC_ICE_CAVERN_IRON_BOOTS_CHEST,
|
||||
RC_ICE_CAVERN_FREESTANDING_POH,
|
||||
RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM,
|
||||
RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM,
|
||||
RC_ICE_CAVERN_GS_HEART_PIECE_ROOM,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST,
|
||||
RC_ICE_CAVERN_MQ_COMPASS_CHEST,
|
||||
RC_ICE_CAVERN_MQ_MAP_CHEST,
|
||||
RC_ICE_CAVERN_MQ_FREESTANDING_POH,
|
||||
RC_ICE_CAVERN_MQ_GS_SCARECROW,
|
||||
RC_ICE_CAVERN_MQ_GS_ICE_BLOCK,
|
||||
RC_ICE_CAVERN_MQ_GS_RED_ICE,
|
||||
},
|
||||
{
|
||||
// Shared Locations
|
||||
RC_SHEIK_IN_ICE_CAVERN,
|
||||
},
|
||||
{});
|
||||
|
||||
DungeonInfo GerudoTrainingGrounds =
|
||||
DungeonInfo("Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, RG_NONE, RG_NONE,
|
||||
RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, RG_GERUDO_TRAINING_GROUNDS_KEY_RING, RG_NONE, 9, 3,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST,
|
||||
},
|
||||
{}, {});
|
||||
|
||||
DungeonInfo GanonsCastle =
|
||||
DungeonInfo("Ganon's Castle", RHT_GANONS_CASTLE, RG_NONE, RG_NONE, RG_GANONS_CASTLE_SMALL_KEY,
|
||||
RG_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_BOSS_KEY, 2, 3,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_GANONS_CASTLE_FOREST_TRIAL_CHEST,
|
||||
RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST,
|
||||
RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST,
|
||||
RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST,
|
||||
RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST,
|
||||
RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST,
|
||||
RC_GANONS_CASTLE_DEKU_SCRUB_LEFT,
|
||||
RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT,
|
||||
RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT,
|
||||
RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY,
|
||||
RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT,
|
||||
RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT,
|
||||
RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER,
|
||||
RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT,
|
||||
RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT,
|
||||
},
|
||||
{
|
||||
// Shared Locations
|
||||
RC_GANONS_TOWER_BOSS_KEY_CHEST,
|
||||
RC_GANON,
|
||||
},
|
||||
{});
|
||||
|
||||
const DungeonArray dungeonList = {
|
||||
&DekuTree, &DodongosCavern, &JabuJabusBelly, &ForestTemple,
|
||||
&FireTemple, &WaterTemple, &SpiritTemple, &ShadowTemple,
|
||||
&BottomOfTheWell, &IceCavern, &GerudoTrainingGrounds, &GanonsCastle,
|
||||
};
|
||||
|
||||
} // namespace Dungeon
|
||||
@@ -1,109 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../randomizerTypes.h"
|
||||
|
||||
namespace Dungeon {
|
||||
class DungeonInfo {
|
||||
public:
|
||||
DungeonInfo(std::string name_, RandomizerHintTextKey hintKey_, RandomizerGet map_, RandomizerGet compass_, RandomizerGet smallKey_,
|
||||
RandomizerGet keyRing_, RandomizerGet bossKey_,
|
||||
uint8_t vanillaKeyCount_, uint8_t mqKeyCount_,
|
||||
std::vector<RandomizerCheck> vanillaLocations_,
|
||||
std::vector<RandomizerCheck> mqLocations_,
|
||||
std::vector<RandomizerCheck> sharedLocations_,
|
||||
std::vector<RandomizerCheck> bossRoomLocations_);
|
||||
~DungeonInfo();
|
||||
|
||||
const std::string& GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
void SetMQ() {
|
||||
masterQuest = true;
|
||||
}
|
||||
|
||||
void ClearMQ() {
|
||||
masterQuest = false;
|
||||
}
|
||||
|
||||
bool IsMQ() const {
|
||||
return masterQuest;
|
||||
}
|
||||
|
||||
void SetKeyRing() {
|
||||
hasKeyRing = true;
|
||||
}
|
||||
|
||||
void ClearKeyRing() {
|
||||
hasKeyRing = false;
|
||||
}
|
||||
|
||||
bool HasKeyRing() const {
|
||||
return hasKeyRing;
|
||||
}
|
||||
|
||||
bool IsVanilla() const {
|
||||
return !masterQuest;
|
||||
}
|
||||
|
||||
uint8_t GetSmallKeyCount() const {
|
||||
return (masterQuest) ? mqKeyCount : vanillaKeyCount;
|
||||
}
|
||||
|
||||
RandomizerHintTextKey GetHintKey() const;
|
||||
RandomizerGet GetSmallKey() const;
|
||||
RandomizerGet GetKeyRing() const;
|
||||
RandomizerGet GetMap() const;
|
||||
RandomizerGet GetCompass() const;
|
||||
RandomizerGet GetBossKey() const;
|
||||
|
||||
void PlaceVanillaMap();
|
||||
void PlaceVanillaCompass();
|
||||
void PlaceVanillaBossKey();
|
||||
void PlaceVanillaSmallKeys();
|
||||
|
||||
// Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla)
|
||||
std::vector<RandomizerCheck> GetDungeonLocations() const;
|
||||
|
||||
// Gets all dungeon locations (MQ + Vanilla)
|
||||
std::vector<RandomizerCheck> GetEveryLocation() const;
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
RandomizerHintTextKey hintKey;
|
||||
RandomizerGet map;
|
||||
RandomizerGet compass;
|
||||
RandomizerGet smallKey;
|
||||
RandomizerGet keyRing;
|
||||
RandomizerGet bossKey;
|
||||
uint8_t vanillaKeyCount;
|
||||
uint8_t mqKeyCount;
|
||||
bool masterQuest = false;
|
||||
bool hasKeyRing = false;
|
||||
std::vector<RandomizerCheck> vanillaLocations;
|
||||
std::vector<RandomizerCheck> mqLocations;
|
||||
std::vector<RandomizerCheck> sharedLocations;
|
||||
std::vector<RandomizerCheck> bossRoomLocations;
|
||||
};
|
||||
|
||||
extern DungeonInfo DekuTree;
|
||||
extern DungeonInfo DodongosCavern;
|
||||
extern DungeonInfo JabuJabusBelly;
|
||||
extern DungeonInfo ForestTemple;
|
||||
extern DungeonInfo FireTemple;
|
||||
extern DungeonInfo WaterTemple;
|
||||
extern DungeonInfo SpiritTemple;
|
||||
extern DungeonInfo ShadowTemple;
|
||||
extern DungeonInfo BottomOfTheWell;
|
||||
extern DungeonInfo IceCavern;
|
||||
extern DungeonInfo GerudoTrainingGrounds;
|
||||
extern DungeonInfo GanonsCastle;
|
||||
|
||||
using DungeonArray = std::array<DungeonInfo*, 12>;
|
||||
|
||||
extern const DungeonArray dungeonList;
|
||||
} // namespace Dungeon
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,289 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "location_access.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include "../randomizer_entrance.h"
|
||||
|
||||
#define ENTRANCE_SHUFFLE_SUCCESS 0
|
||||
#define ENTRANCE_SHUFFLE_FAILURE 1
|
||||
|
||||
extern std::list<EntranceOverride> entranceOverrides;
|
||||
|
||||
enum class EntranceType {
|
||||
None,
|
||||
OwlDrop,
|
||||
Spawn,
|
||||
WarpSong,
|
||||
Dungeon,
|
||||
GanonDungeon,
|
||||
DungeonReverse,
|
||||
Boss,
|
||||
ChildBoss,
|
||||
AdultBoss,
|
||||
Interior,
|
||||
InteriorReverse,
|
||||
SpecialInterior,
|
||||
GrottoGrave,
|
||||
GrottoGraveReverse,
|
||||
Overworld,
|
||||
Extra,
|
||||
Mixed,
|
||||
All,
|
||||
};
|
||||
|
||||
class Entrance {
|
||||
public:
|
||||
|
||||
Entrance(RandomizerRegion connectedRegion_, std::vector<ConditionFn> conditions_met_)
|
||||
: connectedRegion(connectedRegion_) {
|
||||
conditions_met.resize(2);
|
||||
for (size_t i = 0; i < conditions_met_.size(); i++) {
|
||||
conditions_met[i] = conditions_met_[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Resets the glitchless condition for the entrance
|
||||
void SetCondition(ConditionFn newCondition) {
|
||||
conditions_met[0] = newCondition;
|
||||
}
|
||||
|
||||
bool GetConditionsMet() const {
|
||||
if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
return true;
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHLESS)) {
|
||||
return conditions_met[0]();
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHED)) {
|
||||
if (conditions_met[0]()) {
|
||||
return true;
|
||||
} else if (conditions_met[1] != NULL) {
|
||||
return conditions_met[1]();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string to_string() const {
|
||||
return AreaTable(parentRegion)->regionName + " -> " + AreaTable(connectedRegion)->regionName;
|
||||
}
|
||||
|
||||
void SetName(std::string name_ = "") {
|
||||
if (name_ == "") {
|
||||
name = AreaTable(parentRegion)->regionName + " -> " + AreaTable(connectedRegion)->regionName;
|
||||
} else {
|
||||
name = std::move(name_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
void printAgeTimeAccess() {
|
||||
//CitraPrint("Name: ");
|
||||
//CitraPrint(name);
|
||||
auto message = "Child Day: " + std::to_string(CheckConditionAtAgeTime(Logic::IsChild, Logic::AtDay)) + "\t"
|
||||
"Child Night: " + std::to_string(CheckConditionAtAgeTime(Logic::IsChild, Logic::AtNight)) + "\t"
|
||||
"Adult Day: " + std::to_string(CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtDay)) + "\t"
|
||||
"Adult Night: " + std::to_string(CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtNight));
|
||||
//CitraPrint(message);
|
||||
}
|
||||
|
||||
bool ConditionsMet(bool allAgeTimes = false) const {
|
||||
|
||||
Area* parent = AreaTable(parentRegion);
|
||||
int conditionsMet = 0;
|
||||
|
||||
if (allAgeTimes && !parent->AllAccess()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check all possible day/night condition combinations
|
||||
conditionsMet = (parent->childDay && CheckConditionAtAgeTime(Logic::IsChild, Logic::AtDay, allAgeTimes)) +
|
||||
(parent->childNight && CheckConditionAtAgeTime(Logic::IsChild, Logic::AtNight, allAgeTimes)) +
|
||||
(parent->adultDay && CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtDay, allAgeTimes)) +
|
||||
(parent->adultNight && CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtNight, allAgeTimes));
|
||||
|
||||
return conditionsMet && (!allAgeTimes || conditionsMet == 4);
|
||||
}
|
||||
|
||||
uint32_t Getuint32_t() const {
|
||||
return connectedRegion;
|
||||
}
|
||||
|
||||
//set the logic to be a specific age and time of day and see if the condition still holds
|
||||
bool CheckConditionAtAgeTime(bool& age, bool& time, bool passAnyway = false) const {
|
||||
|
||||
Logic::IsChild = false;
|
||||
Logic::IsAdult = false;
|
||||
Logic::AtDay = false;
|
||||
Logic::AtNight = false;
|
||||
|
||||
time = true;
|
||||
age = true;
|
||||
|
||||
Logic::UpdateHelpers();
|
||||
return GetConditionsMet() && (connectedRegion != RR_NONE || passAnyway);
|
||||
}
|
||||
|
||||
RandomizerRegion GetConnectedRegionKey() const {
|
||||
return connectedRegion;
|
||||
}
|
||||
|
||||
Area* GetConnectedRegion() const {
|
||||
return AreaTable(connectedRegion);
|
||||
}
|
||||
|
||||
void SetParentRegion(RandomizerRegion newParent) {
|
||||
parentRegion = newParent;
|
||||
}
|
||||
|
||||
RandomizerRegion GetParentRegionKey() const {
|
||||
return parentRegion;
|
||||
}
|
||||
|
||||
Area* GetParentRegion() const {
|
||||
return AreaTable(parentRegion);
|
||||
}
|
||||
|
||||
void SetNewEntrance(RandomizerRegion newRegion) {
|
||||
connectedRegion = newRegion;
|
||||
}
|
||||
|
||||
void SetAsShuffled() {
|
||||
shuffled = true;
|
||||
}
|
||||
|
||||
bool IsShuffled() const {
|
||||
return shuffled;
|
||||
}
|
||||
|
||||
bool IsAddedToPool() const {
|
||||
return addedToPool;
|
||||
}
|
||||
|
||||
void AddToPool() {
|
||||
addedToPool = true;
|
||||
}
|
||||
|
||||
void RemoveFromPool() {
|
||||
addedToPool = false;
|
||||
}
|
||||
|
||||
void SetAsPrimary() {
|
||||
primary = true;
|
||||
}
|
||||
|
||||
bool IsPrimary() const {
|
||||
return primary;
|
||||
}
|
||||
|
||||
bool IsDecoupled() const {
|
||||
return decoupled;
|
||||
}
|
||||
|
||||
void SetDecoupled() {
|
||||
decoupled = true;
|
||||
}
|
||||
|
||||
int16_t GetIndex() const {
|
||||
return index;
|
||||
}
|
||||
|
||||
void SetIndex(int16_t newIndex) {
|
||||
index = newIndex;
|
||||
}
|
||||
|
||||
int16_t GetBlueWarp() const {
|
||||
return blueWarp;
|
||||
}
|
||||
|
||||
void SetBlueWarp(int16_t newBlueWarp) {
|
||||
blueWarp = newBlueWarp;
|
||||
}
|
||||
|
||||
Entrance* GetAssumed() const {
|
||||
return assumed;
|
||||
}
|
||||
|
||||
void SetReplacement(Entrance* newReplacement) {
|
||||
replacement = newReplacement;
|
||||
}
|
||||
|
||||
Entrance* GetReplacement() const {
|
||||
return replacement;
|
||||
}
|
||||
|
||||
EntranceType GetType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
void SetType(EntranceType newType) {
|
||||
type = newType;
|
||||
}
|
||||
|
||||
Entrance* GetReverse() const {
|
||||
return reverse;
|
||||
}
|
||||
|
||||
void Connect(RandomizerRegion newConnectedRegion) {
|
||||
connectedRegion = newConnectedRegion;
|
||||
AreaTable(newConnectedRegion)->entrances.push_front(this);
|
||||
}
|
||||
|
||||
RandomizerRegion Disconnect() {
|
||||
AreaTable(connectedRegion)->entrances.remove_if([this](const auto entrance){return this == entrance;});
|
||||
RandomizerRegion previouslyConnected = connectedRegion;
|
||||
connectedRegion = RR_NONE;
|
||||
return previouslyConnected;
|
||||
}
|
||||
|
||||
void BindTwoWay(Entrance* otherEntrance) {
|
||||
reverse = otherEntrance;
|
||||
otherEntrance->reverse = this;
|
||||
}
|
||||
|
||||
Entrance* GetNewTarget() {
|
||||
AreaTable(RR_ROOT)->AddExit(RR_ROOT, connectedRegion, []{return true;});
|
||||
Entrance* targetEntrance = AreaTable(RR_ROOT)->GetExit(connectedRegion);
|
||||
targetEntrance->SetReplacement(this);
|
||||
targetEntrance->SetName(GetParentRegion()->regionName + " -> " + GetConnectedRegion()->regionName);
|
||||
return targetEntrance;
|
||||
}
|
||||
|
||||
Entrance* AssumeReachable() {
|
||||
if (assumed == nullptr) {
|
||||
assumed = GetNewTarget();
|
||||
Disconnect();
|
||||
}
|
||||
return assumed;
|
||||
}
|
||||
|
||||
private:
|
||||
RandomizerRegion parentRegion;
|
||||
RandomizerRegion connectedRegion;
|
||||
std::vector<ConditionFn> conditions_met;
|
||||
|
||||
//Entrance Randomizer stuff
|
||||
EntranceType type = EntranceType::None;
|
||||
Entrance* target = nullptr;
|
||||
Entrance* reverse = nullptr;
|
||||
Entrance* assumed = nullptr;
|
||||
Entrance* replacement = nullptr;
|
||||
int16_t index = 0xFFFF;
|
||||
int16_t blueWarp = 0;
|
||||
bool shuffled = false;
|
||||
bool primary = false;
|
||||
bool addedToPool = false;
|
||||
bool decoupled = false;
|
||||
std::string name = "";
|
||||
};
|
||||
|
||||
int ShuffleAllEntrances();
|
||||
void CreateEntranceOverrides();
|
||||
|
||||
extern std::vector<std::list<Entrance*>> playthroughEntrances;
|
||||
extern bool noRandomEntrances;
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "fill.hpp"
|
||||
|
||||
#include "custom_messages.hpp"
|
||||
#include "dungeon.hpp"
|
||||
#include "../dungeon.h"
|
||||
#include "../context.h"
|
||||
#include "item_pool.hpp"
|
||||
#include "location_access.hpp"
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "starting_inventory.hpp"
|
||||
#include "hints.hpp"
|
||||
#include "hint_list.hpp"
|
||||
#include "entrance.hpp"
|
||||
#include "../entrance.h"
|
||||
#include "shops.hpp"
|
||||
#include "pool_functions.hpp"
|
||||
//#include "debug.hpp"
|
||||
#include "soh/Enhancements/randomizer/static_data.h"
|
||||
|
||||
@@ -22,7 +23,7 @@
|
||||
|
||||
using namespace CustomMessages;
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
static bool placementFailure = false;
|
||||
|
||||
@@ -90,14 +91,15 @@ static bool UpdateToDAccess(Entrance* entrance, SearchMode mode) {
|
||||
|
||||
// Various checks that need to pass for the world to be validated as completable
|
||||
static void ValidateWorldChecks(SearchMode& mode, bool checkPoeCollectorAccess, bool checkOtherEntranceAccess, std::vector<RandomizerRegion>& areaPool) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
// Condition for validating Temple of Time Access
|
||||
if (mode == SearchMode::TempleOfTimeAccess && ((Settings::ResolvedStartingAge == AGE_CHILD && AreaTable(RR_TEMPLE_OF_TIME)->Adult()) || (Settings::ResolvedStartingAge == AGE_ADULT && AreaTable(RR_TEMPLE_OF_TIME)->Child()) || !checkOtherEntranceAccess)) {
|
||||
if (mode == SearchMode::TempleOfTimeAccess && ((ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD && AreaTable(RR_TEMPLE_OF_TIME)->Adult()) || (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_ADULT && AreaTable(RR_TEMPLE_OF_TIME)->Child()) || !checkOtherEntranceAccess)) {
|
||||
mode = SearchMode::ValidStartingRegion;
|
||||
}
|
||||
// Condition for validating a valid starting region
|
||||
if (mode == SearchMode::ValidStartingRegion) {
|
||||
bool childAccess = Settings::ResolvedStartingAge == AGE_CHILD || AreaTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Child();
|
||||
bool adultAccess = Settings::ResolvedStartingAge == AGE_ADULT || AreaTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Adult();
|
||||
bool childAccess = ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD || AreaTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Child();
|
||||
bool adultAccess = ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_ADULT || AreaTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Adult();
|
||||
|
||||
Area* kokiri = AreaTable(RR_KOKIRI_FOREST);
|
||||
Area* kakariko = AreaTable(RR_KAKARIKO_VILLAGE);
|
||||
@@ -119,7 +121,7 @@ static void ValidateWorldChecks(SearchMode& mode, bool checkPoeCollectorAccess,
|
||||
Rando::StaticData::RetrieveItem(unplacedItem).ApplyEffect();
|
||||
}
|
||||
// Reset access as the non-starting age
|
||||
if (Settings::ResolvedStartingAge == AGE_CHILD) {
|
||||
if (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) {
|
||||
for (RandomizerRegion areaKey : areaPool) {
|
||||
AreaTable(areaKey)->adultDay = false;
|
||||
AreaTable(areaKey)->adultNight = false;
|
||||
@@ -142,11 +144,11 @@ static int GetMaxGSCount() {
|
||||
//If bridge or LACS is set to tokens, get how many are required
|
||||
int maxBridge = 0;
|
||||
int maxLACS = 0;
|
||||
if (Settings::Bridge.Is(RAINBOWBRIDGE_TOKENS)) {
|
||||
maxBridge = Settings::BridgeTokenCount.Value<uint8_t>();
|
||||
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
|
||||
maxBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value<uint8_t>();
|
||||
}
|
||||
if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_TOKENS)) {
|
||||
maxLACS = Settings::LACSTokenCount.Value<uint8_t>();
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
|
||||
maxLACS = ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value<uint8_t>();
|
||||
}
|
||||
maxBridge = std::max(maxBridge, maxLACS);
|
||||
//Get the max amount of GS which could be useful from token reward locations
|
||||
@@ -171,7 +173,7 @@ static int GetMaxGSCount() {
|
||||
maxUseful = 10;
|
||||
}
|
||||
//Return max of the two possible reasons tokens could be important, minus the tokens in the starting inventory
|
||||
return std::max(maxUseful, maxBridge) - StartingSkulltulaToken.Value<uint8_t>();
|
||||
return std::max(maxUseful, maxBridge) - ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Value<uint8_t>();
|
||||
}
|
||||
|
||||
std::string GetShopItemBaseName(std::string itemName) {
|
||||
@@ -306,7 +308,7 @@ std::vector<RandomizerCheck> GetAccessibleLocations(const std::vector<Randomizer
|
||||
}
|
||||
|
||||
// Add shuffled entrances to the entrance playthrough
|
||||
if (mode == SearchMode::GeneratePlaythrough && exit.IsShuffled() && !exit.IsAddedToPool() && !noRandomEntrances) {
|
||||
if (mode == SearchMode::GeneratePlaythrough && exit.IsShuffled() && !exit.IsAddedToPool() && !ctx->GetEntranceShuffler()->HasNoRandomEntrances()) {
|
||||
entranceSphere.push_back(&exit);
|
||||
exit.AddToPool();
|
||||
// Don't list a two-way coupled entrance from both directions
|
||||
@@ -384,7 +386,8 @@ std::vector<RandomizerCheck> GetAccessibleLocations(const std::vector<Randomizer
|
||||
}
|
||||
//Handle buy items
|
||||
//If ammo drops are off, don't do this step, since buyable ammo becomes logically important
|
||||
else if (AmmoDrops.IsNot(AMMODROPS_NONE) && !(bombchus && bombchusFound) && type == ITEMTYPE_SHOP) {
|
||||
// TODO: Reimplement Ammo Drops setting
|
||||
else if (/*AmmoDrops.IsNot(AMMODROPS_NONE) &&*/ !(bombchus && bombchusFound) && type == ITEMTYPE_SHOP) {
|
||||
//Only check each buy item once
|
||||
std::string buyItem = GetShopItemBaseName(itemName);
|
||||
//Buy item not in list to ignore, add it to list and write to playthrough
|
||||
@@ -394,7 +397,7 @@ std::vector<RandomizerCheck> GetAccessibleLocations(const std::vector<Randomizer
|
||||
}
|
||||
}
|
||||
//Add all other advancement items
|
||||
else if (!bombchus && type != ITEMTYPE_TOKEN && (AmmoDrops.Is(AMMODROPS_NONE) || type != ITEMTYPE_SHOP)) {
|
||||
else if (!bombchus && type != ITEMTYPE_TOKEN && (/*AmmoDrops.Is(AMMODROPS_NONE) ||*/ type != ITEMTYPE_SHOP)) {
|
||||
exclude = false;
|
||||
}
|
||||
//Has not been excluded, add to playthrough
|
||||
@@ -422,8 +425,8 @@ std::vector<RandomizerCheck> GetAccessibleLocations(const std::vector<Randomizer
|
||||
if (mode == SearchMode::GeneratePlaythrough && itemSphere.size() > 0) {
|
||||
ctx->playthroughLocations.push_back(itemSphere);
|
||||
}
|
||||
if (mode == SearchMode::GeneratePlaythrough && entranceSphere.size() > 0 && !noRandomEntrances) {
|
||||
playthroughEntrances.push_back(entranceSphere);
|
||||
if (mode == SearchMode::GeneratePlaythrough && entranceSphere.size() > 0 && !ctx->GetEntranceShuffler()->HasNoRandomEntrances()) {
|
||||
ctx->GetEntranceShuffler()->playthroughEntrances.push_back(entranceSphere);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,7 +608,7 @@ static void AssumedFill(const std::vector<RandomizerGet>& items, const std::vect
|
||||
return;
|
||||
}
|
||||
|
||||
if (Settings::Logic.Is(LOGIC_NONE)) {
|
||||
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC)) {
|
||||
FastFill(items, GetEmptyLocations(allowedLocations), true);
|
||||
return;
|
||||
}
|
||||
@@ -683,7 +686,7 @@ static void AssumedFill(const std::vector<RandomizerGet>& items, const std::vect
|
||||
|
||||
// If ALR is off, then we check beatability after placing the item.
|
||||
// If the game is beatable, then we can stop placing items with logic.
|
||||
if (!LocationsReachable) {
|
||||
if (!ctx->GetOption(RSK_ALL_LOCATIONS_REACHABLE)) {
|
||||
ctx->playthroughBeatable = false;
|
||||
LogicReset();
|
||||
GetAccessibleLocations(ctx->allLocations, SearchMode::CheckBeatable);
|
||||
@@ -702,22 +705,23 @@ static void AssumedFill(const std::vector<RandomizerGet>& items, const std::vect
|
||||
//setting, or randomize one dungeon reward to Link's Pocket if that setting is on
|
||||
static void RandomizeDungeonRewards() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
std::array<uint32_t, 9> rDungeonRewardOverrides{};
|
||||
//quest item bit mask of each stone/medallion for the savefile
|
||||
static constexpr std::array<uint32_t, 9> bitMaskTable = {
|
||||
0x00040000, //Kokiri Emerald
|
||||
0x00080000, //Goron Ruby
|
||||
0x00100000, //Zora Sapphire
|
||||
0x00000001, //Forest Medallion
|
||||
0x00000002, //Fire Medallion
|
||||
0x00000004, //Water Medallion
|
||||
0x00000008, //Spirit Medallion
|
||||
0x00000010, //Shadow Medallion
|
||||
0x00000020, //Light Medallion
|
||||
};
|
||||
// static constexpr std::array<uint32_t, 9> bitMaskTable = {
|
||||
// 0x00040000, //Kokiri Emerald
|
||||
// 0x00080000, //Goron Ruby
|
||||
// 0x00100000, //Zora Sapphire
|
||||
// 0x00000001, //Forest Medallion
|
||||
// 0x00000002, //Fire Medallion
|
||||
// 0x00000004, //Water Medallion
|
||||
// 0x00000008, //Spirit Medallion
|
||||
// 0x00000010, //Shadow Medallion
|
||||
// 0x00000020, //Light Medallion
|
||||
// };
|
||||
int baseOffset = Rando::StaticData::RetrieveItem(RG_KOKIRI_EMERALD).GetItemID();
|
||||
|
||||
//End of Dungeons includes Link's Pocket
|
||||
if (ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
|
||||
//get stones and medallions
|
||||
std::vector<RandomizerGet> rewards = FilterAndEraseFromPool(ItemPool, [](const auto i) {return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;});
|
||||
|
||||
@@ -727,7 +731,7 @@ static void RandomizeDungeonRewards() {
|
||||
ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE);
|
||||
}
|
||||
|
||||
if (Settings::Logic.Is(LOGIC_VANILLA)) { //Place dungeon rewards in vanilla locations
|
||||
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) { //Place dungeon rewards in vanilla locations
|
||||
for (RandomizerCheck loc : Rando::StaticData::dungeonRewardLocations) {
|
||||
ctx->GetItemLocation(loc)->PlaceVanillaItem();
|
||||
}
|
||||
@@ -742,11 +746,11 @@ static void RandomizeDungeonRewards() {
|
||||
//set the player's dungeon reward on file creation instead of pushing it to them at the start.
|
||||
//This is done mainly because players are already familiar with seeing their dungeon reward
|
||||
//before opening up their file
|
||||
if (i == Rando::StaticData::dungeonRewardLocations.size()-1) {
|
||||
LinksPocketRewardBitMask = bitMaskTable[index];
|
||||
}
|
||||
// if (i == Rando::StaticData::dungeonRewardLocations.size()-1) {
|
||||
// LinksPocketRewardBitMask = bitMaskTable[index];
|
||||
// }
|
||||
}
|
||||
} else if (LinksPocketItem.Is(LINKSPOCKETITEM_DUNGEON_REWARD)) {
|
||||
} else if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_DUNGEON_REWARD)) {
|
||||
//get 1 stone/medallion
|
||||
std::vector<RandomizerGet> rewards = FilterFromPool(
|
||||
ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD; });
|
||||
@@ -757,7 +761,7 @@ static void RandomizeDungeonRewards() {
|
||||
}
|
||||
RandomizerGet startingReward = RandomElement(rewards, true);
|
||||
|
||||
LinksPocketRewardBitMask = bitMaskTable[Rando::StaticData::RetrieveItem(startingReward).GetItemID() - baseOffset];
|
||||
//LinksPocketRewardBitMask = bitMaskTable[Rando::StaticData::RetrieveItem(startingReward).GetItemID() - baseOffset];
|
||||
ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingReward);
|
||||
//erase the stone/medallion from the Item Pool
|
||||
FilterAndEraseFromPool(ItemPool, [startingReward](const RandomizerGet i) {return i == startingReward;});
|
||||
@@ -779,7 +783,7 @@ static void FillExcludedLocations() {
|
||||
}
|
||||
|
||||
//Function to handle the Own Dungeon setting
|
||||
static void RandomizeOwnDungeon(const Dungeon::DungeonInfo* dungeon) {
|
||||
static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
std::vector<RandomizerGet> dungeonItems;
|
||||
|
||||
@@ -791,24 +795,24 @@ static void RandomizeOwnDungeon(const Dungeon::DungeonInfo* dungeon) {
|
||||
});
|
||||
|
||||
//filter out locations that may be required to have songs placed at them
|
||||
dungeonLocations = FilterFromPool(dungeonLocations, [](const auto loc){
|
||||
if (ShuffleSongs.Is(SONGSHUFFLE_SONG_LOCATIONS)) {
|
||||
dungeonLocations = FilterFromPool(dungeonLocations, [ctx](const auto loc){
|
||||
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_SONG_LOCATIONS)) {
|
||||
return !(Rando::StaticData::GetLocation(loc)->IsCategory(Category::cSong));
|
||||
}
|
||||
if (ShuffleSongs.Is(SONGSHUFFLE_DUNGEON_REWARDS)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_SONG_LOCATIONS)) {
|
||||
return !(Rando::StaticData::GetLocation(loc)->IsCategory(Category::cSongDungeonReward));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
//Add specific items that need be randomized within this dungeon
|
||||
if (Keysanity.Is(KEYSANITY_OWN_DUNGEON) && dungeon->GetSmallKey() != RG_NONE) {
|
||||
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetSmallKey() != RG_NONE) {
|
||||
std::vector<RandomizerGet> dungeonSmallKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());});
|
||||
AddElementsToPool(dungeonItems, dungeonSmallKeys);
|
||||
}
|
||||
|
||||
if ((BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) ||
|
||||
(GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON) && dungeon->GetBossKey() == RG_GANONS_CASTLE_BOSS_KEY)) {
|
||||
if ((ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) ||
|
||||
(ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON) && dungeon->GetBossKey() == RG_GANONS_CASTLE_BOSS_KEY)) {
|
||||
auto dungeonBossKey = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return i == dungeon->GetBossKey();});
|
||||
AddElementsToPool(dungeonItems, dungeonBossKey);
|
||||
}
|
||||
@@ -817,7 +821,7 @@ static void RandomizeOwnDungeon(const Dungeon::DungeonInfo* dungeon) {
|
||||
AssumedFill(dungeonItems, dungeonLocations);
|
||||
|
||||
//randomize map and compass separately since they're not progressive
|
||||
if (MapsAndCompasses.Is(MAPSANDCOMPASSES_OWN_DUNGEON) && dungeon->GetMap() != RG_NONE && dungeon->GetCompass() != RG_NONE) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetMap() != RG_NONE && dungeon->GetCompass() != RG_NONE) {
|
||||
auto dungeonMapAndCompass = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return i == dungeon->GetMap() || i == dungeon->GetCompass();});
|
||||
AssumedFill(dungeonMapAndCompass, dungeonLocations);
|
||||
}
|
||||
@@ -833,7 +837,6 @@ static void RandomizeOwnDungeon(const Dungeon::DungeonInfo* dungeon) {
|
||||
are randomized separately once the dungeon advancement items have all been placed.*/
|
||||
static void RandomizeDungeonItems() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
using namespace Dungeon;
|
||||
|
||||
//Get Any Dungeon and Overworld group locations
|
||||
std::vector<RandomizerCheck> anyDungeonLocations = FilterFromPool(ctx->allLocations, [](const auto loc){return Rando::StaticData::GetLocation(loc)->IsDungeon();});
|
||||
@@ -843,45 +846,45 @@ static void RandomizeDungeonItems() {
|
||||
std::vector<RandomizerGet> anyDungeonItems;
|
||||
std::vector<RandomizerGet> overworldItems;
|
||||
|
||||
for (auto dungeon : dungeonList) {
|
||||
if (Keysanity.Is(KEYSANITY_ANY_DUNGEON)) {
|
||||
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON)) {
|
||||
auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());});
|
||||
AddElementsToPool(anyDungeonItems, dungeonKeys);
|
||||
} else if (Keysanity.Is(KEYSANITY_OVERWORLD)) {
|
||||
} else if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
|
||||
auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());});
|
||||
AddElementsToPool(overworldItems, dungeonKeys);
|
||||
}
|
||||
|
||||
if (BossKeysanity.Is(BOSSKEYSANITY_ANY_DUNGEON) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) {
|
||||
if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) {
|
||||
auto bossKey = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetBossKey();});
|
||||
AddElementsToPool(anyDungeonItems, bossKey);
|
||||
} else if (BossKeysanity.Is(BOSSKEYSANITY_OVERWORLD) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) {
|
||||
} else if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) {
|
||||
auto bossKey = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetBossKey();});
|
||||
AddElementsToPool(overworldItems, bossKey);
|
||||
}
|
||||
|
||||
if (GanonsBossKey.Is(GANONSBOSSKEY_ANY_DUNGEON)) {
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) {
|
||||
auto ganonBossKey = FilterAndEraseFromPool(ItemPool, [](const auto i){return i == RG_GANONS_CASTLE_BOSS_KEY;});
|
||||
AddElementsToPool(anyDungeonItems, ganonBossKey);
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_OVERWORLD)) {
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) {
|
||||
auto ganonBossKey = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; });
|
||||
AddElementsToPool(overworldItems, ganonBossKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (GerudoKeys.Is(GERUDOKEYS_ANY_DUNGEON)) {
|
||||
if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_ANY_DUNGEON)) {
|
||||
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GERUDO_FORTRESS_SMALL_KEY; });
|
||||
AddElementsToPool(anyDungeonItems, gerudoKeys);
|
||||
} else if (GerudoKeys.Is(GERUDOKEYS_OVERWORLD)) {
|
||||
} else if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_OVERWORLD)) {
|
||||
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GERUDO_FORTRESS_SMALL_KEY; });
|
||||
AddElementsToPool(overworldItems, gerudoKeys);
|
||||
}
|
||||
|
||||
if (ShuffleRewards.Is(REWARDSHUFFLE_ANY_DUNGEON)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_ANY_DUNGEON)) {
|
||||
auto rewards = FilterAndEraseFromPool(
|
||||
ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD; });
|
||||
AddElementsToPool(anyDungeonItems, rewards);
|
||||
} else if (ShuffleRewards.Is(REWARDSHUFFLE_OVERWORLD)) {
|
||||
} else if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_OVERWORLD)) {
|
||||
auto rewards = FilterAndEraseFromPool(
|
||||
ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD; });
|
||||
AddElementsToPool(overworldItems, rewards);
|
||||
@@ -892,11 +895,11 @@ static void RandomizeDungeonItems() {
|
||||
AssumedFill(overworldItems, Rando::StaticData::overworldLocations, true);
|
||||
|
||||
//Randomize maps and compasses after since they're not advancement items
|
||||
for (auto dungeon : dungeonList) {
|
||||
if (MapsAndCompasses.Is(MAPSANDCOMPASSES_ANY_DUNGEON)) {
|
||||
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) {
|
||||
auto mapAndCompassItems = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetMap() || i == dungeon->GetCompass();});
|
||||
AssumedFill(mapAndCompassItems, anyDungeonLocations, true);
|
||||
} else if (MapsAndCompasses.Is(MAPSANDCOMPASSES_OVERWORLD)) {
|
||||
} else if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
|
||||
auto mapAndCompassItems = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetMap() || i == dungeon->GetCompass();});
|
||||
AssumedFill(mapAndCompassItems, Rando::StaticData::overworldLocations, true);
|
||||
}
|
||||
@@ -905,7 +908,7 @@ static void RandomizeDungeonItems() {
|
||||
|
||||
static void RandomizeLinksPocket() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (LinksPocketItem.Is(LINKSPOCKETITEM_ADVANCEMENT)) {
|
||||
if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_ADVANCEMENT)) {
|
||||
//Get all the advancement items don't include tokens
|
||||
std::vector<RandomizerGet> advancementItems = FilterAndEraseFromPool(ItemPool, [](const auto i) {
|
||||
return Rando::StaticData::RetrieveItem(i).IsAdvancement() && Rando::StaticData::RetrieveItem(i).GetItemType() != ITEMTYPE_TOKEN;
|
||||
@@ -916,7 +919,7 @@ static void RandomizeLinksPocket() {
|
||||
AddElementsToPool(ItemPool, advancementItems);
|
||||
|
||||
ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingItem);
|
||||
} else if (LinksPocketItem.Is(LINKSPOCKETITEM_NOTHING)) {
|
||||
} else if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_NOTHING)) {
|
||||
ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE);
|
||||
}
|
||||
}
|
||||
@@ -934,14 +937,14 @@ void VanillaFill() {
|
||||
ctx->GetItemLocation(loc)->PlaceVanillaItem();
|
||||
}
|
||||
//If necessary, handle ER stuff
|
||||
if (ShuffleEntrances) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) {
|
||||
printf("\x1b[7;10HShuffling Entrances...");
|
||||
ShuffleAllEntrances();
|
||||
ctx->GetEntranceShuffler()->ShuffleAllEntrances();
|
||||
printf("\x1b[7;32HDone");
|
||||
}
|
||||
//Finish up
|
||||
ctx->CreateItemOverrides();
|
||||
CreateEntranceOverrides();
|
||||
ctx->GetEntranceShuffler()->CreateEntranceOverrides();
|
||||
CreateWarpSongTexts();
|
||||
}
|
||||
|
||||
@@ -960,7 +963,7 @@ int Fill() {
|
||||
placementFailure = false;
|
||||
//showItemProgress = false;
|
||||
ctx->playthroughLocations.clear();
|
||||
playthroughEntrances.clear();
|
||||
ctx->GetEntranceShuffler()->playthroughEntrances.clear();
|
||||
ctx->wothLocations.clear();
|
||||
AreaTable_Init(); //Reset the world graph to intialize the proper locations
|
||||
ctx->ItemReset(); //Reset shops incase of shopsanity random
|
||||
@@ -973,9 +976,9 @@ int Fill() {
|
||||
//Temporarily add shop items to the ItemPool so that entrance randomization
|
||||
//can validate the world using deku/hylian shields
|
||||
AddElementsToPool(ItemPool, GetMinVanillaShopItems(32)); //assume worst case shopsanity 4
|
||||
if (ShuffleEntrances) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) {
|
||||
printf("\x1b[7;10HShuffling Entrances");
|
||||
if (ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) {
|
||||
if (ctx->GetEntranceShuffler()->ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) {
|
||||
retries++;
|
||||
ClearProgress();
|
||||
continue;
|
||||
@@ -988,11 +991,11 @@ int Fill() {
|
||||
//ctx->showItemProgress = true;
|
||||
//Place shop items first, since a buy shield is needed to place a dungeon reward on Gohma due to access
|
||||
NonShopItems = {};
|
||||
if (Shopsanity.Is(SHOPSANITY_OFF)) {
|
||||
if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF)) {
|
||||
PlaceVanillaShopItems(); //Place vanilla shop items in vanilla location
|
||||
} else {
|
||||
int total_replaced = 0;
|
||||
if (Shopsanity.IsNot(SHOPSANITY_ZERO)) { //Shopsanity 1-4, random
|
||||
if (ctx->GetOption(RSK_SHOPSANITY).IsNot(RO_SHOPSANITY_ZERO_ITEMS)) { //Shopsanity 1-4, random
|
||||
//Initialize NonShopItems
|
||||
ItemAndPrice init;
|
||||
init.Name = Text{"No Item", "Sin objeto", "Pas d'objet"};
|
||||
@@ -1010,7 +1013,7 @@ int Fill() {
|
||||
int shopsanityPrice = GetRandomShopPrice();
|
||||
NonShopItems[TransformShopIndex(i * 8 + itemindex - 1)].Price =
|
||||
shopsanityPrice; // Set price to be retrieved by the patch and textboxes
|
||||
ctx->GetItemLocation(Rando::StaticData::shopLocationLists[i][itemindex - 1])->SetShopsanityPrice(shopsanityPrice);
|
||||
ctx->GetItemLocation(Rando::StaticData::shopLocationLists[i][itemindex - 1])->SetCustomPrice(shopsanityPrice);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1023,7 +1026,7 @@ int Fill() {
|
||||
for (size_t i = 0; i < Rando::StaticData::shopLocationLists.size(); i++) {
|
||||
for (size_t j = 0; j < Rando::StaticData::shopLocationLists[i].size(); j++) {
|
||||
RandomizerCheck loc = Rando::StaticData::shopLocationLists[i][j];
|
||||
if (!(ctx->GetItemLocation(loc)->HasShopsanityPrice())) {
|
||||
if (!(ctx->GetItemLocation(loc)->HasCustomPrice())) {
|
||||
shopLocations.push_back(loc);
|
||||
}
|
||||
}
|
||||
@@ -1036,12 +1039,12 @@ int Fill() {
|
||||
RandomizeDungeonRewards();
|
||||
|
||||
//Place dungeon items restricted to their Own Dungeon
|
||||
for (auto dungeon : Dungeon::dungeonList) {
|
||||
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
RandomizeOwnDungeon(dungeon);
|
||||
}
|
||||
|
||||
//Then Place songs if song shuffle is set to specific locations
|
||||
if (ShuffleSongs.IsNot(SONGSHUFFLE_ANYWHERE)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_ANYWHERE)) {
|
||||
|
||||
//Get each song
|
||||
std::vector<RandomizerGet> songs = FilterAndEraseFromPool(
|
||||
@@ -1049,11 +1052,11 @@ int Fill() {
|
||||
|
||||
//Get each song location
|
||||
std::vector<RandomizerCheck> songLocations;
|
||||
if (ShuffleSongs.Is(SONGSHUFFLE_SONG_LOCATIONS)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_SONG_LOCATIONS)) {
|
||||
songLocations = FilterFromPool(
|
||||
ctx->allLocations, [](const auto loc) { return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cSong); });
|
||||
|
||||
} else if (ShuffleSongs.Is(SONGSHUFFLE_DUNGEON_REWARDS)) {
|
||||
} else if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_DUNGEON_REWARDS)) {
|
||||
songLocations = FilterFromPool(ctx->allLocations, [](const auto loc) {
|
||||
return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cSongDungeonReward);
|
||||
});
|
||||
@@ -1077,14 +1080,14 @@ int Fill() {
|
||||
FastFill(remainingPool, GetAllEmptyLocations(), false);
|
||||
|
||||
//Add prices for scrubsanity, this is unique to SoH because we write/read scrub prices to/from the spoilerfile.
|
||||
if (Scrubsanity.Is(SCRUBSANITY_AFFORDABLE)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_AFFORDABLE)) {
|
||||
for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) {
|
||||
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetScrubsanityPrice(10);
|
||||
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10);
|
||||
}
|
||||
} else if (Scrubsanity.Is(SCRUBSANITY_RANDOM_PRICES)) {
|
||||
} else if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_RANDOM)) {
|
||||
for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) {
|
||||
int randomPrice = GetRandomScrubPrice();
|
||||
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetScrubsanityPrice(randomPrice);
|
||||
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(randomPrice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1097,8 +1100,8 @@ int Fill() {
|
||||
CalculateWotH();
|
||||
printf("Done");
|
||||
ctx->CreateItemOverrides();
|
||||
CreateEntranceOverrides();
|
||||
|
||||
ctx->GetEntranceShuffler()->CreateEntranceOverrides();
|
||||
|
||||
//funny ganon line
|
||||
Text ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText();
|
||||
CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText));
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "custom_messages.hpp"
|
||||
|
||||
#include "../randomizerTypes.h"
|
||||
#include "../context.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
@@ -3238,58 +3239,61 @@ void HintTable_Init() {
|
||||
}
|
||||
|
||||
int32_t StonesRequiredBySettings() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
int32_t stones = 0;
|
||||
if (Settings::Bridge.Is(RAINBOWBRIDGE_STONES)) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)Settings::BridgeStoneCount.Value<uint8_t>() });
|
||||
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Value<uint8_t>() });
|
||||
}
|
||||
if (Settings::Bridge.Is(RAINBOWBRIDGE_REWARDS)) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)Settings::BridgeRewardCount.Value<uint8_t>() - 6 });
|
||||
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value<uint8_t>() - 6 });
|
||||
}
|
||||
if ((Settings::Bridge.Is(RAINBOWBRIDGE_DUNGEONS)) && (Settings::ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON))) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)Settings::BridgeDungeonCount.Value<uint8_t>() - 6 });
|
||||
if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value<uint8_t>() - 6 });
|
||||
}
|
||||
if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_STONES)) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)Settings::LACSStoneCount.Value<uint8_t>() });
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)ctx->GetOption(RSK_LACS_STONE_COUNT).Value<uint8_t>() });
|
||||
}
|
||||
if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_REWARDS)) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)Settings::LACSRewardCount.Value<uint8_t>() - 6 });
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)ctx->GetOption(RSK_LACS_REWARD_COUNT).Value<uint8_t>() - 6 });
|
||||
}
|
||||
if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_DUNGEONS)) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)Settings::LACSDungeonCount.Value<uint8_t>() - 6 });
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
|
||||
stones = std::max<int32_t>({ stones, (int32_t)ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value<uint8_t>() - 6 });
|
||||
}
|
||||
return stones;
|
||||
}
|
||||
|
||||
int32_t MedallionsRequiredBySettings() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
int32_t medallions = 0;
|
||||
if (Settings::Bridge.Is(RAINBOWBRIDGE_MEDALLIONS)) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)Settings::BridgeMedallionCount.Value<uint8_t>() });
|
||||
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Value<uint8_t>() });
|
||||
}
|
||||
if (Settings::Bridge.Is(RAINBOWBRIDGE_REWARDS)) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)Settings::BridgeRewardCount.Value<uint8_t>() - 3 });
|
||||
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value<uint8_t>() - 3 });
|
||||
}
|
||||
if ((Settings::Bridge.Is(RAINBOWBRIDGE_DUNGEONS)) && (Settings::ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON))) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)Settings::BridgeDungeonCount.Value<uint8_t>() - 3 });
|
||||
if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value<uint8_t>() - 3 });
|
||||
}
|
||||
if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_MEDALLIONS)) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)Settings::LACSMedallionCount.Value<uint8_t>() });
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Value<uint8_t>() });
|
||||
}
|
||||
if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_REWARDS)) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)Settings::LACSRewardCount.Value<uint8_t>() - 3 });
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)ctx->GetOption(RSK_LACS_REWARD_COUNT).Value<uint8_t>() - 3 });
|
||||
}
|
||||
if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_DUNGEONS)) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)Settings::LACSDungeonCount.Value<uint8_t>() - 3 });
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
|
||||
medallions = std::max<int32_t>({ medallions, (int32_t)ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value<uint8_t>() - 3 });
|
||||
}
|
||||
return medallions;
|
||||
}
|
||||
|
||||
int32_t TokensRequiredBySettings() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
int32_t tokens = 0;
|
||||
if (Settings::Bridge.Is(RAINBOWBRIDGE_TOKENS)) {
|
||||
tokens = std::max<int32_t>({ tokens, (int32_t)Settings::BridgeTokenCount.Value<uint8_t>() });
|
||||
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
|
||||
tokens = std::max<int32_t>({ tokens, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value<uint8_t>() });
|
||||
}
|
||||
if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_TOKENS)) {
|
||||
tokens = std::max<int32_t>({ tokens, (int32_t)Settings::LACSTokenCount.Value<uint8_t>() });
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
|
||||
tokens = std::max<int32_t>({ tokens, (int32_t)ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value<uint8_t>() });
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
@@ -3297,17 +3301,38 @@ int32_t TokensRequiredBySettings() {
|
||||
std::array<ConditionalAlwaysHint, 10> conditionalAlwaysHints = {
|
||||
std::make_pair(RC_MARKET_10_BIG_POES,
|
||||
[]() {
|
||||
return Settings::BigPoeTargetCount.Value<uint8_t>() >= 3;
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
return ctx->GetOption(RSK_BIG_POE_COUNT).Value<uint8_t>() >= 3;
|
||||
}), // Remember, the option's value being 3 means 4 are required
|
||||
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() { return !Settings::CompleteMaskQuest; }),
|
||||
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH,
|
||||
[]() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
return !ctx->GetOption(RSK_COMPLETE_MASK_QUEST);
|
||||
}),
|
||||
std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME, []() { return StonesRequiredBySettings() < 2; }),
|
||||
std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }),
|
||||
std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }),
|
||||
std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, []() { return false; }),
|
||||
std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 30 && !Settings::Kak30GSHintText; }),
|
||||
std::make_pair(RC_KAK_40_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 40 && !Settings::Kak40GSHintText; }),
|
||||
std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 50 && !Settings::Kak50GSHintText; }),
|
||||
std::make_pair(RC_ZR_FROGS_OCARINA_GAME, []() { return !Settings::FrogsHintText; }),
|
||||
std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD,
|
||||
[]() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
return TokensRequiredBySettings() < 30 && !ctx->GetOption(RSK_KAK_30_SKULLS_HINT);
|
||||
}),
|
||||
std::make_pair(RC_KAK_40_GOLD_SKULLTULA_REWARD,
|
||||
[]() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
return TokensRequiredBySettings() < 40 && !ctx->GetOption(RSK_KAK_40_SKULLS_HINT);
|
||||
}),
|
||||
std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD,
|
||||
[]() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
return TokensRequiredBySettings() < 50 && !ctx->GetOption(RSK_KAK_50_SKULLS_HINT);
|
||||
}),
|
||||
std::make_pair(RC_ZR_FROGS_OCARINA_GAME,
|
||||
[]() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
return !ctx->GetOption(RSK_FROGS_HINT);
|
||||
}),
|
||||
};
|
||||
|
||||
const HintText& Hint(const RandomizerHintTextKey hintKey) {
|
||||
|
||||
@@ -1,24 +1,45 @@
|
||||
#include "hints.hpp"
|
||||
|
||||
#include "custom_messages.hpp"
|
||||
#include "dungeon.hpp"
|
||||
#include "item_pool.hpp"
|
||||
#include "logic.hpp"
|
||||
#include "random.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "fill.hpp"
|
||||
#include "hint_list.hpp"
|
||||
#include "trial.hpp"
|
||||
#include "entrance.hpp"
|
||||
#include "../trial.h"
|
||||
#include "../entrance.h"
|
||||
#include "z64item.h"
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "../randomizerTypes.h"
|
||||
#include "../context.h"
|
||||
#include "pool_functions.hpp"
|
||||
|
||||
using namespace CustomMessages;
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Trial;
|
||||
using namespace Rando;
|
||||
|
||||
const Text& HintText::GetText() const {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)) {
|
||||
return GetObscure();
|
||||
} else if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS)) {
|
||||
return GetAmbiguous();
|
||||
} else {
|
||||
return GetClear();
|
||||
}
|
||||
}
|
||||
|
||||
const Text HintText::GetTextCopy() const {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)) {
|
||||
return GetObscure();
|
||||
} else if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS)) {
|
||||
return GetAmbiguous();
|
||||
} else {
|
||||
return GetClear();
|
||||
}
|
||||
}
|
||||
|
||||
std::array<std::string, HINT_TYPE_MAX> hintTypeNames = {
|
||||
"Static",
|
||||
@@ -126,6 +147,61 @@ constexpr std::array<HintSetting, 4> hintSettingTable{{
|
||||
},
|
||||
}};
|
||||
|
||||
Text AutoFormatHintText(Text unformattedHintText) {
|
||||
std::array<std::string, LANGUAGE_MAX> strings;
|
||||
for (int i = 0; i < LANGUAGE_MAX; i++) {
|
||||
std::string textStr = unformattedHintText.GetForLanguage(i);
|
||||
// RANDOTODO: don't just make manual exceptions
|
||||
bool needsAutomaicNewlines = true;
|
||||
if (textStr == "Erreur 0x69a504:&Traduction manquante^C'est de la faute à Purple Hato!&J'vous jure!" ||
|
||||
textStr == "Mon très cher @:&Viens vite au château, je t'ai préparé&un délicieux gâteau...^À bientôt, Princesse Zelda" ||
|
||||
textStr == "What about Zelda makes you think&she'd be a better ruler than I?^I saved Lon Lon Ranch,&fed the hungry,&and my castle floats." ||
|
||||
textStr == "Many tricks are up my sleeve,&to save yourself&you'd better leave!" ||
|
||||
textStr == "I've learned this spell,&it's really neat,&I'll keep it later&for your treat!" ||
|
||||
textStr == "Sale petit garnement,&tu fais erreur!&C'est maintenant que marque&ta dernière heure!" ||
|
||||
textStr == "Gamin, ton destin achève,&sous mon sort tu périras!&Cette partie ne fut pas brève,&et cette mort, tu subiras!" ||
|
||||
textStr == "Oh! It's @.&I was expecting someone called Sheik.&Do you know what happened to them?" ||
|
||||
textStr == "Ah, c'est @.&J'attendais un certain Sheik.&Tu sais ce qui lui est arrivé?" ||
|
||||
textStr == "They say \"Forgive me, but-^Your script will not be used.&....After all...^The one writing the rest of the script...&will be me.\"") {
|
||||
needsAutomaicNewlines = false;
|
||||
}
|
||||
|
||||
if (needsAutomaicNewlines) {
|
||||
// insert newlines either manually or when encountering a '&'
|
||||
constexpr size_t lineLength = 34;
|
||||
size_t lastNewline = 0;
|
||||
while (lastNewline + lineLength < textStr.length()) {
|
||||
size_t carrot = textStr.find('^', lastNewline);
|
||||
size_t ampersand = textStr.find('&', lastNewline);
|
||||
size_t lastSpace = textStr.rfind(' ', lastNewline + lineLength);
|
||||
size_t lastPeriod = textStr.rfind('.', lastNewline + lineLength);
|
||||
// replace '&' first if it's within the newline range
|
||||
if (ampersand < lastNewline + lineLength) {
|
||||
lastNewline = ampersand;
|
||||
// or move the lastNewline cursor to the next line if a '^' is encountered
|
||||
} else if (carrot < lastNewline + lineLength) {
|
||||
lastNewline = carrot + 1;
|
||||
// some lines need to be split but don't have spaces, look for periods instead
|
||||
} else if (lastSpace == std::string::npos) {
|
||||
textStr.replace(lastPeriod, 1, ".&");
|
||||
lastNewline = lastPeriod + 2;
|
||||
} else {
|
||||
textStr.replace(lastSpace, 1, "&");
|
||||
lastNewline = lastSpace + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo add colors (see `AddColorsAndFormat` in `custom_messages.cpp`)
|
||||
textStr.erase(std::remove(textStr.begin(), textStr.end(), '#'), textStr.end());
|
||||
strings[i] = textStr;
|
||||
}
|
||||
|
||||
return Text(strings[0], strings[1], strings[2]);
|
||||
}
|
||||
|
||||
std::array<DungeonHintInfo, 10> dungeonInfoData;
|
||||
|
||||
Text childAltarText;
|
||||
Text adultAltarText;
|
||||
Text ganonText;
|
||||
@@ -328,7 +404,7 @@ static void AddHint(Text hint, const RandomizerCheck gossipStone, const std::vec
|
||||
//GetLocation(gossipStone)->SetPlacedItem(gossipStone);
|
||||
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
ctx->AddHint((RandomizerHintKey)((gossipStone - RC_DMC_GOSSIP_STONE) + 1), hint, hintedLocation, hintType, GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText());
|
||||
ctx->AddHint((RandomizerHintKey)((gossipStone - RC_COLOSSUS_GOSSIP_STONE) + 1), AutoFormatHintText(hint), hintedLocation, hintType, GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText());
|
||||
ctx->GetItemLocation(gossipStone)->SetPlacedItem(RG_HINT);
|
||||
}
|
||||
|
||||
@@ -366,31 +442,31 @@ static bool CreateHint(RandomizerCheck hintedLocation, uint8_t copies, HintType
|
||||
|
||||
//make hint text
|
||||
Text finalHint;
|
||||
Text prefix = Hint(RHT_PREFIX).GetText();
|
||||
Text prefix = ::Hint(RHT_PREFIX).GetText();
|
||||
std::vector<uint8_t> colours = {QM_GREEN, QM_RED};
|
||||
if (type == HINT_TYPE_WOTH){
|
||||
Text regionText = GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
|
||||
finalHint = prefix + "%r#" + regionText + "#%w" + Hint(RHT_WAY_OF_THE_HERO).GetText();
|
||||
finalHint = prefix + "%r#" + regionText + "#%w" + ::Hint(RHT_WAY_OF_THE_HERO).GetText();
|
||||
colours = {QM_LBLUE};
|
||||
}
|
||||
else if(type == HINT_TYPE_BARREN){
|
||||
Text regionText = GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
|
||||
finalHint = prefix + Hint(RHT_PLUNDERING).GetText() + "%r#" + regionText + "#%w" + Hint(RHT_FOOLISH).GetText();
|
||||
finalHint = prefix + ::Hint(RHT_PLUNDERING).GetText() + "%r#" + regionText + "#%w" + ::Hint(RHT_FOOLISH).GetText();
|
||||
colours = {QM_PINK};
|
||||
}
|
||||
else {
|
||||
Text itemText = ctx->GetItemLocation(hintedLocation)->GetPlacedItem().GetHint().GetText();
|
||||
if (type >= HINT_TYPE_ALWAYS && type < HINT_TYPE_NAMED_ITEM){
|
||||
Text locationText = Rando::StaticData::GetLocation(hintedLocation)->GetHint()->GetText();
|
||||
finalHint = prefix + locationText + " #"+itemText+"#.";
|
||||
finalHint = prefix + "%r" + locationText + " %g#"+itemText+"#%w.";
|
||||
}
|
||||
else if (type == HINT_TYPE_NAMED_ITEM || type == HINT_TYPE_RANDOM){
|
||||
Text regionText = GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
|
||||
// RANDOTODO: reconsider dungeon vs non-dungeon item location hints when boss shuffle mixed pools happens
|
||||
if (Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()) {
|
||||
finalHint = prefix+"%r#"+regionText+"#%w "+Hint(RHT_HOARDS).GetText()+" %g#"+itemText+"#%w.";
|
||||
finalHint = prefix+"%r#"+regionText+"#%w "+::Hint(RHT_HOARDS).GetText()+" %g#"+itemText+"#%w.";
|
||||
} else {
|
||||
finalHint = prefix+"%r#"+itemText+"#%w "+Hint(RHT_CAN_BE_FOUND_AT).GetText()+" %g#"+regionText+"#%w.";
|
||||
finalHint = prefix+"%r#"+itemText+"#%w "+::Hint(RHT_CAN_BE_FOUND_AT).GetText()+" %g#"+regionText+"#%w.";
|
||||
colours = {QM_RED, QM_GREEN};
|
||||
}
|
||||
}
|
||||
@@ -500,37 +576,40 @@ static std::vector<RandomizerCheck> CalculateBarrenRegions() {
|
||||
}
|
||||
|
||||
static void CreateTrialHints(uint8_t copies) {
|
||||
Text prefix = Hint(RHT_PREFIX).GetText();
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
Text prefix = ::Hint(RHT_PREFIX).GetText();
|
||||
//six trials
|
||||
if (RandomGanonsTrials && GanonsTrialsCount.Is(6)) {
|
||||
AddHintCopies(copies, prefix + Hint(RHT_SIX_TRIALS).GetText(), {QM_PINK}, HINT_TYPE_TRIAL);
|
||||
if (ctx->GetOption(RSK_GANONS_TRIALS).IsNot(RO_GANONS_TRIALS_SKIP) && ctx->GetOption(RSK_TRIAL_COUNT).Is(6)) {
|
||||
AddHintCopies(copies, prefix + ::Hint(RHT_SIX_TRIALS).GetText(), {QM_PINK}, HINT_TYPE_TRIAL);
|
||||
//zero trials
|
||||
} else if (RandomGanonsTrials && GanonsTrialsCount.Is(0)) {
|
||||
AddHintCopies(copies, prefix + Hint(RHT_ZERO_TRIALS).GetText(), {QM_YELLOW}, HINT_TYPE_TRIAL);
|
||||
} else if (ctx->GetOption(RSK_GANONS_TRIALS).IsNot(RO_GANONS_TRIALS_SKIP) && ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) {
|
||||
AddHintCopies(copies, prefix + ::Hint(RHT_ZERO_TRIALS).GetText(), {QM_YELLOW}, HINT_TYPE_TRIAL);
|
||||
//4 or 5 required trials
|
||||
} else if (GanonsTrialsCount.Is(5) || GanonsTrialsCount.Is(4)) {
|
||||
} else if (ctx->GetOption(RSK_TRIAL_COUNT).Is(5) || ctx->GetOption(RSK_TRIAL_COUNT).Is(4)) {
|
||||
//get skipped trials
|
||||
std::vector<TrialInfo*> trials = {};
|
||||
auto trialList = ctx->GetTrials()->GetTrialList();
|
||||
trials.assign(trialList.begin(), trialList.end());
|
||||
auto skippedTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsSkipped();});
|
||||
|
||||
//create a hint for each skipped trial
|
||||
for (auto& trial : skippedTrials) {
|
||||
//make hint
|
||||
auto hint = prefix+"#"+trial->GetName()+"#"+Hint(RHT_FOUR_TO_FIVE_TRIALS).GetText();
|
||||
auto hint = prefix+"#"+trial->GetName()+"#"+::Hint(RHT_FOUR_TO_FIVE_TRIALS).GetText();
|
||||
AddHintCopies(copies, hint, {QM_YELLOW}, HINT_TYPE_TRIAL);
|
||||
}
|
||||
//1 to 3 trials
|
||||
} else if (GanonsTrialsCount.Value<uint8_t>() >= 1 && GanonsTrialsCount.Value<uint8_t>() <= 3) {
|
||||
} else if (ctx->GetOption(RSK_TRIAL_COUNT).Value<uint8_t>() >= 1 && ctx->GetOption(RSK_TRIAL_COUNT).Value<uint8_t>() <= 3) {
|
||||
//get requried trials
|
||||
std::vector<TrialInfo*> trials = {};
|
||||
auto trialList = ctx->GetTrials()->GetTrialList();
|
||||
trials.assign(trialList.begin(), trialList.end());
|
||||
auto requiredTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsRequired();});
|
||||
|
||||
//create a hint for each required trial
|
||||
for (auto& trial : requiredTrials) {
|
||||
//make hint
|
||||
auto hint = prefix+"#"+trial->GetName()+"#"+Hint(RHT_ONE_TO_THREE_TRIALS).GetText();
|
||||
auto hint = prefix+"#"+trial->GetName()+"#"+::Hint(RHT_ONE_TO_THREE_TRIALS).GetText();
|
||||
AddHintCopies(copies, hint, {QM_PINK}, HINT_TYPE_TRIAL);
|
||||
}
|
||||
}
|
||||
@@ -539,7 +618,7 @@ static void CreateTrialHints(uint8_t copies) {
|
||||
//RANDOTODO clean this mess up once starting items are expanded
|
||||
void CreateGanonAndSheikText() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if(Settings::LightArrowHintText){
|
||||
if(ctx->GetOption(RSK_LIGHT_ARROWS_HINT)){
|
||||
//Get the location of the light arrows
|
||||
auto lightArrowLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
|
||||
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_LIGHT_ARROWS;
|
||||
@@ -548,9 +627,9 @@ void CreateGanonAndSheikText() {
|
||||
std::vector<RandomizerCheck> locsToCheck = {RC_GANONDORF_HINT};
|
||||
|
||||
//If there is no light arrow location, it was in the player's inventory at the start
|
||||
auto hint = Hint(RHT_LIGHT_ARROW_LOCATION_HINT);
|
||||
auto hint = ::Hint(RHT_LIGHT_ARROW_LOCATION_HINT);
|
||||
if (lightArrowLocation.empty()) {
|
||||
ganonHintText = hint.GetText()+Hint(RHT_YOUR_POCKET).GetText();
|
||||
ganonHintText = hint.GetText()+::Hint(RHT_YOUR_POCKET).GetText();
|
||||
lightArrowHintLoc = "Link's Pocket";
|
||||
} else {
|
||||
ganonHintText = hint.GetText() + "%r" + lightArrowArea + "%w";
|
||||
@@ -564,36 +643,37 @@ void CreateGanonAndSheikText() {
|
||||
});
|
||||
Text masterSwordArea = GetHintRegion(ctx->GetItemLocation(masterSwordLocation[0])->GetParentRegionKey())->GetHint().GetText();
|
||||
|
||||
if (ShuffleMasterSword) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) {
|
||||
// Add second text box
|
||||
ganonHintText = ganonHintText + "^";
|
||||
if (masterSwordLocation.empty()) {
|
||||
ganonHintText = ganonHintText + Hint(RHT_MASTER_SWORD_LOCATION_HINT).GetText() + "%r" + Hint(RHT_YOUR_POCKET).GetText() + "%w";
|
||||
ganonHintText = ganonHintText + ::Hint(RHT_MASTER_SWORD_LOCATION_HINT).GetText() + "%r" + ::Hint(RHT_YOUR_POCKET).GetText() + "%w";
|
||||
masterSwordHintLoc = "Link's Pocket";
|
||||
} else {
|
||||
ganonHintText = ganonHintText + Hint(RHT_MASTER_SWORD_LOCATION_HINT).GetText() + "%r" + masterSwordArea + "%w";
|
||||
ganonHintText = ganonHintText + ::Hint(RHT_MASTER_SWORD_LOCATION_HINT).GetText() + "%r" + masterSwordArea + "%w";
|
||||
masterSwordHintLoc = Rando::StaticData::GetLocation(masterSwordLocation[0])->GetName();
|
||||
}
|
||||
ganonHintText = ganonHintText + "!";
|
||||
}
|
||||
|
||||
CreateMessageFromTextObject(0x70CC, 0, 2, 3, AddColorsAndFormat(ganonHintText));
|
||||
ctx->AddHint(RH_GANONDORF_HINT, ganonHintText, lightArrowLocation[0], HINT_TYPE_STATIC, GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText());
|
||||
//CreateMessageFromTextObject(0x70CC, 0, 2, 3, AddColorsAndFormat(ganonHintText));
|
||||
ctx->AddHint(RH_GANONDORF_HINT, AutoFormatHintText(ganonHintText), lightArrowLocation[0], HINT_TYPE_STATIC, GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText());
|
||||
|
||||
if (!Settings::GanonsTrialsCount.Is(0)) {
|
||||
sheikText = Hint(RHT_SHEIK_LIGHT_ARROW_HINT).GetText() + lightArrowArea + "%w.";
|
||||
if(!ctx->GetOption(RSK_TRIAL_COUNT).Is(0)){
|
||||
sheikText = ::Hint(RHT_SHEIK_LIGHT_ARROW_HINT).GetText() + lightArrowArea + "%w.";
|
||||
locsToCheck = {RC_GANONDORF_HINT, RC_SHEIK_HINT_GC, RC_SHEIK_HINT_MQ_GC};
|
||||
|
||||
if (ShuffleMasterSword) {
|
||||
sheikText = sheikText + "^" + Hint(RHT_SHEIK_MASTER_SWORD_LOCATION_HINT).GetText() + masterSwordArea + "%w.";
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) {
|
||||
sheikText = sheikText + "^" + ::Hint(RHT_SHEIK_MASTER_SWORD_LOCATION_HINT).GetText() + masterSwordArea + "%w.";
|
||||
}
|
||||
}
|
||||
|
||||
if (IsReachableWithout(locsToCheck, lightArrowLocation[0], true)) {
|
||||
ctx->GetItemLocation(lightArrowLocation[0])->SetAsHinted();
|
||||
}
|
||||
ctx->AddHint(RH_SHEIK_LIGHT_ARROWS, AutoFormatHintText(sheikText), lightArrowLocation[0], HINT_TYPE_STATIC, lightArrowArea);
|
||||
|
||||
if (ShuffleMasterSword) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) {
|
||||
if (IsReachableWithout(locsToCheck, masterSwordLocation[0], true)) {
|
||||
ctx->GetItemLocation(masterSwordLocation[0])->SetHintKey(RH_GANONDORF_HINT);
|
||||
ctx->GetItemLocation(masterSwordLocation[0])->SetAsHinted();
|
||||
@@ -610,7 +690,7 @@ static Text BuildDungeonRewardText(const RandomizerGet itemKey, bool isChild) {
|
||||
RandomizerCheck location = FilterFromPool(ctx->allLocations, [itemKey, ctx](const RandomizerCheck loc) {
|
||||
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == itemKey;
|
||||
})[0];
|
||||
if (IsReachableWithout({altarLoc}, location, true) || ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON)){ //RANDOTODO check if works properly
|
||||
if (IsReachableWithout({altarLoc}, location, true) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)){ //RANDOTODO check if works properly
|
||||
ctx->GetItemLocation(location)->SetAsHinted();
|
||||
}
|
||||
|
||||
@@ -623,28 +703,29 @@ static Text BuildDungeonRewardText(const RandomizerGet itemKey, bool isChild) {
|
||||
}
|
||||
|
||||
static Text BuildDoorOfTimeText() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
std::string itemObtained;
|
||||
Text doorOfTimeText;
|
||||
|
||||
if (OpenDoorOfTime.Is(OPENDOOROFTIME_OPEN)) {
|
||||
if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN)) {
|
||||
itemObtained = "$o";
|
||||
doorOfTimeText = Hint(RHT_CHILD_ALTAR_TEXT_END_DOTOPEN).GetText();
|
||||
doorOfTimeText = ::Hint(RHT_CHILD_ALTAR_TEXT_END_DOTOPEN).GetText();
|
||||
|
||||
} else if (OpenDoorOfTime.Is(OPENDOOROFTIME_SONGONLY)) {
|
||||
} else if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_SONGONLY)) {
|
||||
itemObtained = "$c";
|
||||
doorOfTimeText = Hint(RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY).GetText();
|
||||
doorOfTimeText = ::Hint(RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY).GetText();
|
||||
|
||||
} else if (OpenDoorOfTime.Is(OPENDOOROFTIME_CLOSED)) {
|
||||
} else if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_CLOSED)) {
|
||||
itemObtained = "$i";
|
||||
doorOfTimeText = Hint(RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED).GetText();
|
||||
doorOfTimeText = ::Hint(RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED).GetText();
|
||||
}
|
||||
|
||||
return Text()+itemObtained+doorOfTimeText;
|
||||
}
|
||||
|
||||
//insert the required number into the hint and set the singular/plural form
|
||||
static Text BuildCountReq(const RandomizerHintTextKey req, const Option& count) {
|
||||
Text requirement = Hint(req).GetTextCopy();
|
||||
static Text BuildCountReq(const RandomizerHintTextKey req, const Rando::Option& count) {
|
||||
Text requirement = ::Hint(req).GetTextCopy();
|
||||
if (count.Value<uint8_t>() == 1) {
|
||||
requirement.SetForm(SINGULAR);
|
||||
} else {
|
||||
@@ -655,80 +736,82 @@ static Text BuildCountReq(const RandomizerHintTextKey req, const Option& count)
|
||||
}
|
||||
|
||||
static Text BuildBridgeReqsText() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
Text bridgeText;
|
||||
|
||||
if (Bridge.Is(RAINBOWBRIDGE_OPEN)) {
|
||||
bridgeText = Hint(RHT_BRIDGE_OPEN_HINT).GetText();
|
||||
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN)) {
|
||||
bridgeText = ::Hint(RHT_BRIDGE_OPEN_HINT).GetText();
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_VANILLA)) {
|
||||
bridgeText = Hint(RHT_BRIDGE_VANILLA_HINT).GetText();
|
||||
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA)) {
|
||||
bridgeText = ::Hint(RHT_BRIDGE_VANILLA_HINT).GetText();
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_STONES)) {
|
||||
bridgeText = BuildCountReq(RHT_BRIDGE_STONES_HINT, BridgeStoneCount);
|
||||
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) {
|
||||
bridgeText = BuildCountReq(RHT_BRIDGE_STONES_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT));
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_MEDALLIONS)) {
|
||||
bridgeText = BuildCountReq(RHT_BRIDGE_MEDALLIONS_HINT, BridgeMedallionCount);
|
||||
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) {
|
||||
bridgeText = BuildCountReq(RHT_BRIDGE_MEDALLIONS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT));
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_REWARDS)) {
|
||||
bridgeText = BuildCountReq(RHT_BRIDGE_REWARDS_HINT, BridgeRewardCount);
|
||||
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
|
||||
bridgeText = BuildCountReq(RHT_BRIDGE_REWARDS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT));
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_DUNGEONS)) {
|
||||
bridgeText = BuildCountReq(RHT_BRIDGE_DUNGEONS_HINT, BridgeDungeonCount);
|
||||
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) {
|
||||
bridgeText = BuildCountReq(RHT_BRIDGE_DUNGEONS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT));
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_TOKENS)) {
|
||||
bridgeText = BuildCountReq(RHT_BRIDGE_TOKENS_HINT, BridgeTokenCount);
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_GREG)) {
|
||||
bridgeText = Hint(RHT_BRIDGE_GREG_HINT).GetText();
|
||||
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
|
||||
bridgeText = BuildCountReq(RHT_BRIDGE_TOKENS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT));
|
||||
|
||||
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)) {
|
||||
bridgeText = ::Hint(RHT_BRIDGE_GREG_HINT).GetText();
|
||||
}
|
||||
|
||||
return Text()+"$l"+bridgeText+"^";
|
||||
}
|
||||
|
||||
static Text BuildGanonBossKeyText() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
Text ganonBossKeyText;
|
||||
|
||||
if (GanonsBossKey.Is(GANONSBOSSKEY_START_WITH)) {
|
||||
ganonBossKeyText = Hint(RHT_GANON_BK_START_WITH_HINT).GetText();
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH)) {
|
||||
ganonBossKeyText = ::Hint(RHT_GANON_BK_START_WITH_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA)) {
|
||||
ganonBossKeyText = Hint(RHT_GANON_BK_VANILLA_HINT).GetText();
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) {
|
||||
ganonBossKeyText = ::Hint(RHT_GANON_BK_VANILLA_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON)) {
|
||||
ganonBossKeyText = Hint(RHT_GANON_BK_OWN_DUNGEON_HINT).GetText();
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON)) {
|
||||
ganonBossKeyText = ::Hint(RHT_GANON_BK_OWN_DUNGEON_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_ANY_DUNGEON)) {
|
||||
ganonBossKeyText = Hint(RHT_GANON_BK_ANY_DUNGEON_HINT).GetText();
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) {
|
||||
ganonBossKeyText = ::Hint(RHT_GANON_BK_ANY_DUNGEON_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_OVERWORLD)) {
|
||||
ganonBossKeyText = Hint(RHT_GANON_BK_OVERWORLD_HINT).GetText();
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) {
|
||||
ganonBossKeyText = ::Hint(RHT_GANON_BK_OVERWORLD_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_ANYWHERE)) {
|
||||
ganonBossKeyText = Hint(RHT_GANON_BK_ANYWHERE_HINT).GetText();
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANYWHERE)) {
|
||||
ganonBossKeyText = ::Hint(RHT_GANON_BK_ANYWHERE_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_FINAL_GS_REWARD)) {
|
||||
ganonBossKeyText = Hint(RHT_GANON_BK_SKULLTULA_HINT).GetText();
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) {
|
||||
ganonBossKeyText = ::Hint(RHT_GANON_BK_SKULLTULA_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_VANILLA)) {
|
||||
ganonBossKeyText = Hint(RHT_LACS_VANILLA_HINT).GetText();
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_VANILLA)) {
|
||||
ganonBossKeyText = ::Hint(RHT_LACS_VANILLA_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_STONES)) {
|
||||
ganonBossKeyText = BuildCountReq(RHT_LACS_STONES_HINT, LACSStoneCount);
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
|
||||
ganonBossKeyText = BuildCountReq(RHT_LACS_STONES_HINT, ctx->GetOption(RSK_LACS_STONE_COUNT));
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_MEDALLIONS)) {
|
||||
ganonBossKeyText = BuildCountReq(RHT_LACS_MEDALLIONS_HINT, LACSMedallionCount);
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
|
||||
ganonBossKeyText = BuildCountReq(RHT_LACS_MEDALLIONS_HINT, ctx->GetOption(RSK_LACS_MEDALLION_COUNT));
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_REWARDS)) {
|
||||
ganonBossKeyText = BuildCountReq(RHT_LACS_REWARDS_HINT, LACSRewardCount);
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
|
||||
ganonBossKeyText = BuildCountReq(RHT_LACS_REWARDS_HINT, ctx->GetOption(RSK_LACS_REWARD_COUNT));
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_DUNGEONS)) {
|
||||
ganonBossKeyText = BuildCountReq(RHT_LACS_DUNGEONS_HINT, LACSDungeonCount);
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
|
||||
ganonBossKeyText = BuildCountReq(RHT_LACS_DUNGEONS_HINT, ctx->GetOption(RSK_LACS_DUNGEON_COUNT));
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_TOKENS)) {
|
||||
ganonBossKeyText = BuildCountReq(RHT_LACS_TOKENS_HINT, LACSTokenCount);
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
|
||||
ganonBossKeyText = BuildCountReq(RHT_LACS_TOKENS_HINT, ctx->GetOption(RSK_LACS_TOKEN_COUNT));
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_TRIFORCE_HUNT)) {
|
||||
ganonBossKeyText = Hint(RHT_GANON_BK_TRIFORCE_HINT).GetText();
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
|
||||
ganonBossKeyText = ::Hint(RHT_GANON_BK_TRIFORCE_HINT).GetText();
|
||||
}
|
||||
|
||||
return Text()+"$b"+ganonBossKeyText+"^";
|
||||
@@ -738,14 +821,15 @@ void CreateAltarText() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
|
||||
//Child Altar Text
|
||||
if (AltarHintText) {
|
||||
childAltarText = Hint(RHT_SPIRITUAL_STONE_TEXT_START).GetText()+"^"+
|
||||
if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) {
|
||||
childAltarText = ::Hint(RHT_SPIRITUAL_STONE_TEXT_START).GetText()+"^"+
|
||||
//Spiritual Stones
|
||||
(StartingKokiriEmerald.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
// TODO: Starting Inventory Dungeon Rewards
|
||||
(/*StartingKokiriEmerald.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_KOKIRI_EMERALD, true)) +
|
||||
(StartingGoronRuby.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
(/*StartingGoronRuby.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_GORON_RUBY, true)) +
|
||||
(StartingZoraSapphire.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
(/*StartingZoraSapphire.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_ZORA_SAPPHIRE, true)) +
|
||||
//How to open Door of Time, the event trigger is necessary to read the altar multiple times
|
||||
BuildDoorOfTimeText();
|
||||
@@ -754,24 +838,24 @@ void CreateAltarText() {
|
||||
}
|
||||
ctx->AddHint(RH_ALTAR_CHILD, childAltarText, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
|
||||
CreateMessageFromTextObject(0x7040, 0, 2, 3, AddColorsAndFormat(childAltarText, {QM_GREEN, QM_RED, QM_BLUE}));
|
||||
//CreateMessageFromTextObject(0x7040, 0, 2, 3, AddColorsAndFormat(childAltarText, {QM_GREEN, QM_RED, QM_BLUE}));
|
||||
|
||||
//Adult Altar Text
|
||||
adultAltarText = Hint(RHT_ADULT_ALTAR_TEXT_START).GetText() + "^";
|
||||
if (AltarHintText) {
|
||||
adultAltarText = ::Hint(RHT_ADULT_ALTAR_TEXT_START).GetText() + "^";
|
||||
if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) {
|
||||
adultAltarText = adultAltarText +
|
||||
//Medallion Areas
|
||||
(StartingLightMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
(/*StartingLightMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_LIGHT_MEDALLION, false)) +
|
||||
(StartingForestMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
(/*StartingForestMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_FOREST_MEDALLION, false)) +
|
||||
(StartingFireMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
(/*StartingFireMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_FIRE_MEDALLION, false)) +
|
||||
(StartingWaterMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
(/*StartingWaterMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_WATER_MEDALLION, false)) +
|
||||
(StartingSpiritMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
(/*StartingSpiritMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_SPIRIT_MEDALLION, false)) +
|
||||
(StartingShadowMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
(/*StartingShadowMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_SHADOW_MEDALLION, false));
|
||||
}
|
||||
adultAltarText = adultAltarText +
|
||||
@@ -782,8 +866,8 @@ void CreateAltarText() {
|
||||
BuildGanonBossKeyText()+
|
||||
|
||||
//End
|
||||
Hint(RHT_ADULT_ALTAR_TEXT_END).GetText();
|
||||
CreateMessageFromTextObject(0x7088, 0, 2, 3, AddColorsAndFormat(adultAltarText, {QM_RED, QM_YELLOW, QM_GREEN, QM_RED, QM_BLUE, QM_YELLOW, QM_PINK, QM_RED, QM_RED, QM_RED, QM_RED}));
|
||||
::Hint(RHT_ADULT_ALTAR_TEXT_END).GetText();
|
||||
//CreateMessageFromTextObject(0x7088, 0, 2, 3, AddColorsAndFormat(adultAltarText, {QM_RED, QM_YELLOW, QM_GREEN, QM_RED, QM_BLUE, QM_YELLOW, QM_PINK, QM_RED, QM_RED, QM_RED, QM_RED}));
|
||||
ctx->AddHint(RH_ALTAR_ADULT, adultAltarText, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
}
|
||||
|
||||
@@ -798,25 +882,25 @@ void CreateMerchantsHints() {
|
||||
|
||||
|
||||
Text medigoronText =
|
||||
Hint(RHT_MEDIGORON_DIALOG_FIRST).GetText() + medigoronItemText + Hint(RHT_MEDIGORON_DIALOG_SECOND).GetText();
|
||||
Text grannyText = grannyItemText + Hint(RHT_GRANNY_DIALOG).GetText();
|
||||
Text carpetSalesmanTextOne = Hint(RHT_CARPET_SALESMAN_DIALOG_FIRST).GetText() + carpetSalesmanItemText +
|
||||
Hint(RHT_CARPET_SALESMAN_DIALOG_SECOND).GetText();
|
||||
Text carpetSalesmanTextTwo = Hint(RHT_CARPET_SALESMAN_DIALOG_THIRD).GetText() + carpetSalesmanItemClearText +
|
||||
Hint(RHT_CARPET_SALESMAN_DIALOG_FOURTH).GetText();
|
||||
::Hint(RHT_MEDIGORON_DIALOG_FIRST).GetText() + medigoronItemText + ::Hint(RHT_MEDIGORON_DIALOG_SECOND).GetText();
|
||||
Text grannyText = grannyItemText + ::Hint(RHT_GRANNY_DIALOG).GetText();
|
||||
Text carpetSalesmanTextOne = ::Hint(RHT_CARPET_SALESMAN_DIALOG_FIRST).GetText() + carpetSalesmanItemText +
|
||||
::Hint(RHT_CARPET_SALESMAN_DIALOG_SECOND).GetText();
|
||||
Text carpetSalesmanTextTwo = ::Hint(RHT_CARPET_SALESMAN_DIALOG_THIRD).GetText() + carpetSalesmanItemClearText +
|
||||
::Hint(RHT_CARPET_SALESMAN_DIALOG_FOURTH).GetText();
|
||||
|
||||
CreateMessageFromTextObject(0x9120, 0, 2, 3, AddColorsAndFormat(medigoronText, { QM_RED, QM_GREEN }));
|
||||
CreateMessageFromTextObject(0x9121, 0, 2, 3, AddColorsAndFormat(grannyText, { QM_RED, QM_GREEN }));
|
||||
CreateMessageFromTextObject(0x6077, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextOne, { QM_RED, QM_GREEN }));
|
||||
CreateMessageFromTextObject(0x6078, 0, 2, 3,
|
||||
AddColorsAndFormat(carpetSalesmanTextTwo, { QM_RED, QM_YELLOW, QM_RED }));
|
||||
ctx->AddHint(RH_MEDIGORON, medigoronText, RC_GC_MEDIGORON, HINT_TYPE_STATIC, GetHintRegion(RR_GORON_CITY)->GetHint().GetText());
|
||||
ctx->AddHint(RH_GRANNYS_SHOP, grannyText, RC_KAK_GRANNYS_SHOP, HINT_TYPE_STATIC, GetHintRegion(RR_KAKARIKO_VILLAGE)->GetHint().GetText());
|
||||
ctx->AddHint(RH_WASTELAND_BOMBCHU_SALESMAN, carpetSalesmanTextOne, RC_WASTELAND_BOMBCHU_SALESMAN, HINT_TYPE_STATIC, GetHintRegion(RR_HAUNTED_WASTELAND)->GetHint().GetText());
|
||||
// CreateMessageFromTextObject(0x9120, 0, 2, 3, AddColorsAndFormat(medigoronText, { QM_RED, QM_GREEN }));
|
||||
// CreateMessageFromTextObject(0x9121, 0, 2, 3, AddColorsAndFormat(grannyText, { QM_RED, QM_GREEN }));
|
||||
// CreateMessageFromTextObject(0x6077, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextOne, { QM_RED, QM_GREEN }));
|
||||
// CreateMessageFromTextObject(0x6078, 0, 2, 3,
|
||||
// AddColorsAndFormat(carpetSalesmanTextTwo, { QM_RED, QM_YELLOW, QM_RED }));
|
||||
// ctx->AddHint(RH_MEDIGORON, AutoFormatHintText(medigoronText), RC_GC_MEDIGORON, HINT_TYPE_STATIC, GetHintRegion(RR_GORON_CITY)->GetHint().GetText());
|
||||
// ctx->AddHint(RH_GRANNYS_SHOP, AutoFormatHintText(grannyText), RC_KAK_GRANNYS_SHOP, HINT_TYPE_STATIC, GetHintRegion(RR_KAKARIKO_VILLAGE)->GetHint().GetText());
|
||||
// ctx->AddHint(RH_WASTELAND_BOMBCHU_SALESMAN, AutoFormatHintText(carpetSalesmanTextOne), RC_WASTELAND_BOMBCHU_SALESMAN, HINT_TYPE_STATIC, GetHintRegion(RR_HAUNTED_WASTELAND)->GetHint().GetText());
|
||||
}
|
||||
|
||||
//RANDOTODO add Better Links Pocket and starting item handling once more starting items are added
|
||||
void CreateSpecialItemHint(uint32_t item, std::vector<RandomizerCheck> hints, RandomizerHintTextKey text1, RandomizerHintTextKey text2, Text& textLoc, std::string& nameLoc, bool condition, bool yourpocket = false) {
|
||||
void CreateSpecialItemHint(uint32_t item, RandomizerHintKey hintKey, std::vector<RandomizerCheck> hints, RandomizerHintTextKey text1, RandomizerHintTextKey text2, Text& textLoc, std::string& nameLoc, bool condition, bool yourpocket = false) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if(condition){
|
||||
RandomizerCheck location = FilterFromPool(ctx->allLocations, [item, ctx](const RandomizerCheck loc) {
|
||||
@@ -828,8 +912,9 @@ void CreateSpecialItemHint(uint32_t item, std::vector<RandomizerCheck> hints, Ra
|
||||
}
|
||||
|
||||
Text area = GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText();
|
||||
textLoc = Hint(text1).GetText() + area + Hint(text2).GetText();
|
||||
textLoc = ::Hint(text1).GetText() + area + ::Hint(text2).GetText();
|
||||
nameLoc = Rando::StaticData::GetLocation(location)->GetName();
|
||||
ctx->AddHint(hintKey, AutoFormatHintText(textLoc), location, HINT_TYPE_STATIC, area);
|
||||
} else {
|
||||
textLoc = Text();
|
||||
nameLoc = "";
|
||||
@@ -838,7 +923,8 @@ void CreateSpecialItemHint(uint32_t item, std::vector<RandomizerCheck> hints, Ra
|
||||
|
||||
|
||||
void CreateWarpSongTexts() {
|
||||
if (!ShuffleWarpSongs) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (!ctx->GetOption(RSK_WARP_SONG_HINTS)) {
|
||||
warpMinuetText = Text();
|
||||
warpBoleroText = Text();
|
||||
warpSerenadeText = Text();
|
||||
@@ -865,21 +951,27 @@ void CreateWarpSongTexts() {
|
||||
switch (entrance->GetIndex()) {
|
||||
case 0x0600: // minuet
|
||||
warpMinuetText = resolvedHint;
|
||||
ctx->AddHint(RH_MINUET_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint);
|
||||
break;
|
||||
case 0x04F6: // bolero
|
||||
warpBoleroText = resolvedHint;
|
||||
ctx->AddHint(RH_BOLERO_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint);
|
||||
break;
|
||||
case 0x0604: // serenade
|
||||
warpSerenadeText = resolvedHint;
|
||||
ctx->AddHint(RH_SERENADE_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint);
|
||||
break;
|
||||
case 0x01F1: // requiem
|
||||
warpRequiemText = resolvedHint;
|
||||
ctx->AddHint(RH_REQUIEM_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint);
|
||||
break;
|
||||
case 0x0568: // nocturne
|
||||
warpNocturneText = resolvedHint;
|
||||
break;
|
||||
warpNocturneText = resolvedHint;
|
||||
ctx->AddHint(RH_NOCTURNE_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint);
|
||||
break;
|
||||
case 0x05F4: // prelude
|
||||
warpPreludeText = resolvedHint;
|
||||
ctx->AddHint(RH_PRELUDE_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1008,32 +1100,32 @@ uint8_t PlaceHints(std::array<uint8_t, HINT_TYPE_MAX>& selectedHints,
|
||||
void CreateStoneHints() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
SPDLOG_DEBUG("\nNOW CREATING HINTS\n");
|
||||
const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value<uint8_t>()];
|
||||
const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).Value<uint8_t>()];
|
||||
std::array<HintDistributionSetting, (int)HINT_TYPE_MAX> distTable = hintSetting.distTable;
|
||||
|
||||
uint8_t* remainingDungeonWothHints = new uint8_t(hintSetting.dungeonsWothLimit);
|
||||
uint8_t* remainingDungeonBarrenHints = new uint8_t(hintSetting.dungeonsBarrenLimit);
|
||||
|
||||
// Apply Special hint exclusions with no requirements
|
||||
if (Settings::Kak10GSHintText){
|
||||
if (ctx->GetOption(RSK_KAK_10_SKULLS_HINT)){
|
||||
ctx->GetItemLocation(RC_KAK_10_GOLD_SKULLTULA_REWARD)->SetAsHinted();
|
||||
}
|
||||
if (Settings::Kak20GSHintText){
|
||||
if (ctx->GetOption(RSK_KAK_20_SKULLS_HINT)){
|
||||
ctx->GetItemLocation(RC_KAK_20_GOLD_SKULLTULA_REWARD)->SetAsHinted();
|
||||
}
|
||||
if (Settings::Kak30GSHintText){
|
||||
if (ctx->GetOption(RSK_KAK_30_SKULLS_HINT)){
|
||||
ctx->GetItemLocation(RC_KAK_30_GOLD_SKULLTULA_REWARD)->SetAsHinted();
|
||||
}
|
||||
if (Settings::Kak40GSHintText){
|
||||
if (ctx->GetOption(RSK_KAK_40_SKULLS_HINT)){
|
||||
ctx->GetItemLocation(RC_KAK_40_GOLD_SKULLTULA_REWARD)->SetAsHinted();
|
||||
}
|
||||
if (Settings::Kak50GSHintText){
|
||||
if (ctx->GetOption(RSK_KAK_50_SKULLS_HINT)){
|
||||
ctx->GetItemLocation(RC_KAK_50_GOLD_SKULLTULA_REWARD)->SetAsHinted();
|
||||
}
|
||||
if (Settings::FrogsHintText){
|
||||
if (ctx->GetOption(RSK_FROGS_HINT)){
|
||||
ctx->GetItemLocation(RC_ZR_FROGS_OCARINA_GAME)->SetAsHinted();
|
||||
}
|
||||
if (Settings::skipChildZelda){
|
||||
if (ctx->GetOption(RSK_SKIP_CHILD_ZELDA)){
|
||||
ctx->GetItemLocation(RC_SONG_FROM_IMPA)->SetAsHinted();
|
||||
}
|
||||
|
||||
@@ -1045,7 +1137,7 @@ void CreateStoneHints() {
|
||||
auto alwaysHintLocations = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
|
||||
return ((Rando::StaticData::GetLocation(loc)->GetHint()->GetType() == HintCategory::Always) ||
|
||||
// If we have Rainbow Bridge set to Greg, add a hint for where Greg is
|
||||
(Bridge.Is(RAINBOWBRIDGE_GREG) &&
|
||||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG) &&
|
||||
ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) &&
|
||||
ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsHintedAt());
|
||||
});
|
||||
@@ -1086,16 +1178,17 @@ void CreateStoneHints() {
|
||||
}
|
||||
|
||||
void CreateAllHints(){
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
CreateGanonAndSheikText();
|
||||
CreateAltarText();
|
||||
CreateSpecialItemHint(RG_PROGRESSIVE_HOOKSHOT, {RC_DAMPE_HINT}, RHT_DAMPE_DIARY01, RHT_DAMPE_DIARY02, dampesText, dampeHintLoc, (bool)DampeHintText);
|
||||
CreateSpecialItemHint(RG_GREG_RUPEE, {RC_GREG_HINT}, RHT_GREG_HINT01, RHT_GREG_HINT02, gregText, gregHintLoc, (bool)GregHintText);
|
||||
CreateSpecialItemHint(RG_PROGRESSIVE_MAGIC_METER, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, RHT_SARIA_TEXT01, RHT_SARIA_TEXT02, sariaText, sariaHintLoc, (bool)SariaHintText);
|
||||
CreateSpecialItemHint(RG_PROGRESSIVE_HOOKSHOT, RH_DAMPES_DIARY, {RC_DAMPE_HINT}, RHT_DAMPE_DIARY01, RHT_DAMPE_DIARY02, dampesText, dampeHintLoc, (bool)ctx->GetOption(RSK_DAMPES_DIARY_HINT));
|
||||
CreateSpecialItemHint(RG_GREG_RUPEE, RH_GREG_RUPEE, {RC_GREG_HINT}, RHT_GREG_HINT01, RHT_GREG_HINT02, gregText, gregHintLoc, (bool)ctx->GetOption(RSK_GREG_HINT));
|
||||
CreateSpecialItemHint(RG_PROGRESSIVE_MAGIC_METER, RH_SARIA, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, RHT_SARIA_TEXT01, RHT_SARIA_TEXT02, sariaText, sariaHintLoc, (bool)ctx->GetOption(RSK_SARIA_HINT));
|
||||
|
||||
if (ShuffleMerchants.Is(SHUFFLEMERCHANTS_HINTS)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ON_HINT)) {
|
||||
CreateMerchantsHints();
|
||||
}
|
||||
if (GossipStoneHints.IsNot(HINTS_NO_HINTS)) {
|
||||
if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE)) {
|
||||
printf("\x1b[10;10HCreating Hints...");
|
||||
CreateStoneHints();
|
||||
printf("Done");
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
|
||||
#include "text.hpp"
|
||||
#include "random.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "dungeon.hpp"
|
||||
#include <functional>
|
||||
|
||||
struct HintDistributionSetting {
|
||||
HintType type;
|
||||
size_t weight;
|
||||
@@ -55,7 +52,8 @@ public:
|
||||
: obscureText(std::move(obscureText_)),
|
||||
ambiguousText(std::move(ambiguousText_)),
|
||||
clearText(std::move(clearText_)),
|
||||
type(type_) {}
|
||||
type(type_) {
|
||||
}
|
||||
|
||||
static auto Item(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Item};
|
||||
@@ -162,25 +160,9 @@ public:
|
||||
return clearText;
|
||||
}
|
||||
|
||||
const Text& GetText() const {
|
||||
if (Settings::ClearerHints.Is(HINTMODE_OBSCURE)) {
|
||||
return GetObscure();
|
||||
} else if (Settings::ClearerHints.Is(HINTMODE_AMBIGUOUS)){
|
||||
return GetAmbiguous();
|
||||
} else {
|
||||
return GetClear();
|
||||
}
|
||||
}
|
||||
const Text& GetText() const;
|
||||
|
||||
const Text GetTextCopy() const {
|
||||
if (Settings::ClearerHints.Is(HINTMODE_OBSCURE)) {
|
||||
return GetObscure();
|
||||
} else if (Settings::ClearerHints.Is(HINTMODE_AMBIGUOUS)){
|
||||
return GetAmbiguous();
|
||||
} else {
|
||||
return GetClear();
|
||||
}
|
||||
}
|
||||
const Text GetTextCopy() const;
|
||||
|
||||
HintCategory GetType() const {
|
||||
return type;
|
||||
@@ -204,8 +186,15 @@ private:
|
||||
|
||||
using ConditionalAlwaysHint = std::pair<RandomizerCheck, std::function<bool()>>;
|
||||
|
||||
typedef enum {
|
||||
DUNGEON_NEITHER,
|
||||
DUNGEON_BARREN,
|
||||
DUNGEON_WOTH,
|
||||
} DungeonHintInfo;
|
||||
|
||||
//10 dungeons as GTG and GC are excluded
|
||||
extern std::array<DungeonInfo, 10> dungeonInfoData;
|
||||
extern std::array<DungeonHintInfo, 10> dungeonInfoData;
|
||||
|
||||
extern std::array<ConditionalAlwaysHint, 10> conditionalAlwaysHints;
|
||||
|
||||
extern RandomizerHintTextKey GetHintRegionHintKey(const RandomizerRegion area);
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
#include "item_pool.hpp"
|
||||
|
||||
#include "dungeon.hpp"
|
||||
#include "../dungeon.h"
|
||||
#include "fill.hpp"
|
||||
#include "../static_data.h"
|
||||
#include "../context.h"
|
||||
#include "pool_functions.hpp"
|
||||
#include "random.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "z64item.h"
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
|
||||
using namespace Settings;
|
||||
using namespace Dungeon;
|
||||
|
||||
std::vector<RandomizerGet> ItemPool = {};
|
||||
std::vector<RandomizerGet> PendingJunkPool = {};
|
||||
std::vector<uint8_t> IceTrapModels = {};
|
||||
const std::array<RandomizerGet, 9> dungeonRewards = {
|
||||
RG_KOKIRI_EMERALD,
|
||||
RG_GORON_RUBY,
|
||||
@@ -432,9 +426,10 @@ static void AddRandomBottle(std::vector<RandomizerGet>& bottlePool) {
|
||||
}
|
||||
|
||||
RandomizerGet GetJunkItem() {
|
||||
if (IceTrapValue.Is(ICETRAPS_MAYHEM) || IceTrapValue.Is(ICETRAPS_ONSLAUGHT)) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_MAYHEM) || ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_ONSLAUGHT)) {
|
||||
return RG_ICE_TRAP;
|
||||
} else if (IceTrapValue.Is(ICETRAPS_EXTRA)) {
|
||||
} else if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_EXTRA)) {
|
||||
return RandomElement(JunkPoolItems);
|
||||
}
|
||||
//Ice Trap is the last item in JunkPoolItems, so subtract 1 to never hit that index
|
||||
@@ -504,10 +499,10 @@ static void PlaceVanillaDekuScrubItems() {
|
||||
ctx->PlaceItemInLocation(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RG_DEKU_SEEDS_30, false, true);
|
||||
|
||||
//Dungeon Scrubs
|
||||
if (DekuTree.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::DEKU_TREE)->IsMQ()) {
|
||||
ctx->PlaceItemInLocation(RC_DEKU_TREE_MQ_DEKU_SCRUB, RG_DEKU_SHIELD, false, true);
|
||||
}
|
||||
if (DodongosCavern.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::DODONGOS_CAVERN)->IsMQ()) {
|
||||
ctx->PlaceItemInLocation(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RG_DEKU_STICK_1, false, true);
|
||||
ctx->PlaceItemInLocation(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RG_DEKU_SEEDS_30, false, true);
|
||||
ctx->PlaceItemInLocation(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RG_DEKU_SHIELD, false, true);
|
||||
@@ -519,10 +514,10 @@ static void PlaceVanillaDekuScrubItems() {
|
||||
ctx->PlaceItemInLocation(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RG_DEKU_SEEDS_30, false, true);
|
||||
ctx->PlaceItemInLocation(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RG_DEKU_SHIELD, false, true);
|
||||
}
|
||||
if (JabuJabusBelly.IsVanilla()) {
|
||||
if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsVanilla()) {
|
||||
ctx->PlaceItemInLocation(RC_JABU_JABUS_BELLY_DEKU_SCRUB, RG_DEKU_NUTS_5, false, true);
|
||||
}
|
||||
if (GanonsCastle.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::GANONS_CASTLE)->IsMQ()) {
|
||||
ctx->PlaceItemInLocation(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RG_GREEN_POTION_REFILL, false, true);
|
||||
ctx->PlaceItemInLocation(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RG_BOMBS_5, false, true);
|
||||
ctx->PlaceItemInLocation(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RG_ARROWS_30, false, true);
|
||||
@@ -539,23 +534,28 @@ static void PlaceVanillaDekuScrubItems() {
|
||||
}
|
||||
|
||||
static void PlaceVanillaMapsAndCompasses() {
|
||||
for (auto dungeon : dungeonList) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
dungeon->PlaceVanillaMap();
|
||||
dungeon->PlaceVanillaCompass();
|
||||
}
|
||||
}
|
||||
|
||||
static void PlaceVanillaSmallKeys() {
|
||||
for (auto dungeon : dungeonList) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
dungeon->PlaceVanillaSmallKeys();
|
||||
}
|
||||
}
|
||||
|
||||
static void PlaceVanillaBossKeys() {
|
||||
for (auto dungeon : dungeonList) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
dungeon->PlaceVanillaBossKey();
|
||||
}
|
||||
}
|
||||
// TODO: This feels like it could be moved to Dungeons class and probably shorten
|
||||
// a few function call chains. Needs investigation.
|
||||
|
||||
static void PlaceVanillaCowMilk() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
@@ -569,7 +569,7 @@ static void PlaceVanillaCowMilk() {
|
||||
ctx->PlaceItemInLocation(RC_LLR_TOWER_LEFT_COW, RG_MILK, false, true);
|
||||
ctx->PlaceItemInLocation(RC_LLR_TOWER_RIGHT_COW, RG_MILK, false, true);
|
||||
|
||||
if (JabuJabusBelly.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsMQ()) {
|
||||
ctx->PlaceItemInLocation(RC_JABU_JABUS_BELLY_MQ_COW, RG_MILK, false, true);
|
||||
}
|
||||
}
|
||||
@@ -590,6 +590,7 @@ static void SetScarceItemPool() {
|
||||
}
|
||||
|
||||
static void SetMinimalItemPool() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
ReplaceMaxItem(RG_PROGRESSIVE_BOMBCHUS, 1);
|
||||
ReplaceMaxItem(RG_BOMBCHU_5, 1);
|
||||
ReplaceMaxItem(RG_BOMBCHU_10, 0);
|
||||
@@ -604,7 +605,7 @@ static void SetMinimalItemPool() {
|
||||
ReplaceMaxItem(RG_PROGRESSIVE_BOMB_BAG, 1);
|
||||
ReplaceMaxItem(RG_PIECE_OF_HEART, 0);
|
||||
// Need an extra heart container when starting with 1 heart to be able to reach 3 hearts
|
||||
ReplaceMaxItem(RG_HEART_CONTAINER, (StartingHearts.Value<uint8_t>() == 18)? 1 : 0);
|
||||
ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).Value<uint8_t>() == 18)? 1 : 0);
|
||||
}
|
||||
|
||||
void GenerateItemPool() {
|
||||
@@ -613,63 +614,63 @@ void GenerateItemPool() {
|
||||
PendingJunkPool.clear();
|
||||
|
||||
//Initialize ice trap models to always major items
|
||||
IceTrapModels = {
|
||||
GI_SHIELD_MIRROR,
|
||||
GI_BOOMERANG,
|
||||
GI_LENS,
|
||||
GI_HAMMER,
|
||||
GI_BOOTS_IRON,
|
||||
GI_BOOTS_HOVER,
|
||||
GI_STONE_OF_AGONY,
|
||||
GI_DINS_FIRE,
|
||||
GI_FARORES_WIND,
|
||||
GI_NAYRUS_LOVE,
|
||||
GI_ARROW_FIRE,
|
||||
GI_ARROW_ICE,
|
||||
GI_ARROW_LIGHT,
|
||||
0xB8, //Double defense
|
||||
GI_CLAIM_CHECK,
|
||||
0x80, //Progressive hookshot
|
||||
0x81, //Progressive strength
|
||||
0x82, //Progressive bomb bag
|
||||
0x83, //Progressive bow
|
||||
0x84, //Progressive slingshot
|
||||
0x85, //Progressive wallet
|
||||
0x86, //Progressive scale
|
||||
0x8A, //Progressive magic
|
||||
ctx->possibleIceTrapModels = {
|
||||
RG_MIRROR_SHIELD,
|
||||
RG_BOOMERANG,
|
||||
RG_LENS_OF_TRUTH,
|
||||
RG_MEGATON_HAMMER,
|
||||
RG_IRON_BOOTS,
|
||||
RG_HOVER_BOOTS,
|
||||
RG_STONE_OF_AGONY,
|
||||
RG_DINS_FIRE,
|
||||
RG_FARORES_WIND,
|
||||
RG_NAYRUS_LOVE,
|
||||
RG_FIRE_ARROWS,
|
||||
RG_ICE_ARROWS,
|
||||
RG_LIGHT_ARROWS,
|
||||
RG_DOUBLE_DEFENSE, //Double defense
|
||||
RG_CLAIM_CHECK,
|
||||
RG_PROGRESSIVE_HOOKSHOT, //Progressive hookshot
|
||||
RG_PROGRESSIVE_STRENGTH, //Progressive strength
|
||||
RG_PROGRESSIVE_BOMB_BAG, //Progressive bomb bag
|
||||
RG_PROGRESSIVE_BOW, //Progressive bow
|
||||
RG_PROGRESSIVE_SLINGSHOT, //Progressive slingshot
|
||||
RG_PROGRESSIVE_WALLET, //Progressive wallet
|
||||
RG_PROGRESSIVE_SCALE, //Progressive scale
|
||||
RG_PROGRESSIVE_MAGIC_METER, //Progressive magic
|
||||
};
|
||||
//Check song shuffle and dungeon reward shuffle just for ice traps
|
||||
if (ShuffleSongs.Is(SONGSHUFFLE_ANYWHERE)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE)) {
|
||||
//Push item ids for songs
|
||||
IceTrapModels.push_back(0xC1);
|
||||
IceTrapModels.push_back(0xC2);
|
||||
IceTrapModels.push_back(0xC3);
|
||||
IceTrapModels.push_back(0xC4);
|
||||
IceTrapModels.push_back(0xC5);
|
||||
IceTrapModels.push_back(0xC6);
|
||||
IceTrapModels.push_back(0xBB);
|
||||
IceTrapModels.push_back(0xBC);
|
||||
IceTrapModels.push_back(0xBD);
|
||||
IceTrapModels.push_back(0xBE);
|
||||
IceTrapModels.push_back(0xBF);
|
||||
IceTrapModels.push_back(0xC0);
|
||||
ctx->possibleIceTrapModels.push_back(RG_ZELDAS_LULLABY);
|
||||
ctx->possibleIceTrapModels.push_back(RG_EPONAS_SONG);
|
||||
ctx->possibleIceTrapModels.push_back(RG_SARIAS_SONG);
|
||||
ctx->possibleIceTrapModels.push_back(RG_SUNS_SONG);
|
||||
ctx->possibleIceTrapModels.push_back(RG_SONG_OF_TIME);
|
||||
ctx->possibleIceTrapModels.push_back(RG_SONG_OF_STORMS);
|
||||
ctx->possibleIceTrapModels.push_back(RG_MINUET_OF_FOREST);
|
||||
ctx->possibleIceTrapModels.push_back(RG_BOLERO_OF_FIRE);
|
||||
ctx->possibleIceTrapModels.push_back(RG_SERENADE_OF_WATER);
|
||||
ctx->possibleIceTrapModels.push_back(RG_REQUIEM_OF_SPIRIT);
|
||||
ctx->possibleIceTrapModels.push_back(RG_NOCTURNE_OF_SHADOW);
|
||||
ctx->possibleIceTrapModels.push_back(RG_PRELUDE_OF_LIGHT);
|
||||
}
|
||||
if (ShuffleRewards.Is(REWARDSHUFFLE_ANYWHERE)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_ANYWHERE)) {
|
||||
//Push item ids for dungeon rewards
|
||||
IceTrapModels.push_back(0xCB);
|
||||
IceTrapModels.push_back(0xCC);
|
||||
IceTrapModels.push_back(0xCD);
|
||||
IceTrapModels.push_back(0xCE);
|
||||
IceTrapModels.push_back(0xCF);
|
||||
IceTrapModels.push_back(0xD0);
|
||||
IceTrapModels.push_back(0xD1);
|
||||
IceTrapModels.push_back(0xD2);
|
||||
IceTrapModels.push_back(0xD3);
|
||||
ctx->possibleIceTrapModels.push_back(RG_KOKIRI_EMERALD);
|
||||
ctx->possibleIceTrapModels.push_back(RG_GORON_RUBY);
|
||||
ctx->possibleIceTrapModels.push_back(RG_ZORA_SAPPHIRE);
|
||||
ctx->possibleIceTrapModels.push_back(RG_FOREST_MEDALLION);
|
||||
ctx->possibleIceTrapModels.push_back(RG_FIRE_MEDALLION);
|
||||
ctx->possibleIceTrapModels.push_back(RG_WATER_MEDALLION);
|
||||
ctx->possibleIceTrapModels.push_back(RG_SPIRIT_MEDALLION);
|
||||
ctx->possibleIceTrapModels.push_back(RG_SHADOW_MEDALLION);
|
||||
ctx->possibleIceTrapModels.push_back(RG_LIGHT_MEDALLION);
|
||||
}
|
||||
|
||||
if (TriforceHunt.Is(TRIFORCE_HUNT_ON)) {
|
||||
IceTrapModels.push_back(0xDF);
|
||||
AddItemToMainPool(RG_TRIFORCE_PIECE, Settings::TriforceHuntTotal.Value<uint8_t>());
|
||||
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
|
||||
ctx->possibleIceTrapModels.push_back(RG_TRIFORCE_PIECE);
|
||||
AddItemToMainPool(RG_TRIFORCE_PIECE, ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Value<uint8_t>());
|
||||
ctx->PlaceItemInLocation(RC_TRIFORCE_COMPLETED, RG_TRIFORCE); // Win condition
|
||||
ctx->PlaceItemInLocation(RC_GANON, GetJunkItem(), false, true);
|
||||
} else {
|
||||
@@ -680,66 +681,66 @@ void GenerateItemPool() {
|
||||
ctx->PlaceItemInLocation(RC_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER);
|
||||
ctx->PlaceItemInLocation(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP);
|
||||
|
||||
if (ShuffleKokiriSword) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_KOKIRI_SWORD)) {
|
||||
AddItemToMainPool(RG_KOKIRI_SWORD);
|
||||
IceTrapModels.push_back(GI_SWORD_KOKIRI);
|
||||
ctx->possibleIceTrapModels.push_back(RG_KOKIRI_SWORD);
|
||||
} else {
|
||||
ctx->PlaceItemInLocation(RC_KF_KOKIRI_SWORD_CHEST, RG_KOKIRI_SWORD, false, true);
|
||||
}
|
||||
|
||||
if (ShuffleMasterSword) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) {
|
||||
AddItemToMainPool(RG_MASTER_SWORD);
|
||||
IceTrapModels.push_back(0xE0); //Master Sword without the GI enum
|
||||
ctx->possibleIceTrapModels.push_back(RG_MASTER_SWORD); //Master Sword without the GI enum
|
||||
} else {
|
||||
ctx->PlaceItemInLocation(RC_TOT_MASTER_SWORD, RG_MASTER_SWORD, false, true);
|
||||
}
|
||||
|
||||
if (ShuffleWeirdEgg) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_WEIRD_EGG)) {
|
||||
AddItemToMainPool(RG_WEIRD_EGG);
|
||||
IceTrapModels.push_back(GI_WEIRD_EGG);
|
||||
ctx->possibleIceTrapModels.push_back(RG_WEIRD_EGG);
|
||||
} else {
|
||||
ctx->PlaceItemInLocation(RC_HC_MALON_EGG, RG_WEIRD_EGG, false, true);
|
||||
}
|
||||
|
||||
if (ShuffleOcarinas) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_OCARINA)) {
|
||||
AddItemToMainPool(RG_PROGRESSIVE_OCARINA, 2);
|
||||
if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) {
|
||||
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
|
||||
AddItemToPool(PendingJunkPool, RG_PROGRESSIVE_OCARINA);
|
||||
}
|
||||
IceTrapModels.push_back(0x8B); //Progressive ocarina
|
||||
ctx->possibleIceTrapModels.push_back(RG_PROGRESSIVE_OCARINA); //Progressive ocarina
|
||||
} else {
|
||||
ctx->PlaceItemInLocation(RC_LW_GIFT_FROM_SARIA, RG_PROGRESSIVE_OCARINA, false, true);
|
||||
ctx->PlaceItemInLocation(RC_HF_OCARINA_OF_TIME_ITEM, RG_PROGRESSIVE_OCARINA, false, true);
|
||||
}
|
||||
|
||||
if (ShuffleCows) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_COWS)) {
|
||||
//9 total cow locations
|
||||
for (uint8_t i = 0; i < 9; i++) {
|
||||
AddItemToMainPool(GetJunkItem());
|
||||
}
|
||||
//extra location for Jabu MQ
|
||||
if (JabuJabusBelly.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsMQ()) {
|
||||
AddItemToMainPool(GetJunkItem());
|
||||
}
|
||||
} else {
|
||||
PlaceVanillaCowMilk();
|
||||
}
|
||||
|
||||
if (ShuffleMagicBeans) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MAGIC_BEANS)) {
|
||||
AddItemToMainPool(RG_MAGIC_BEAN_PACK);
|
||||
if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) {
|
||||
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
|
||||
AddItemToPool(PendingJunkPool, RG_MAGIC_BEAN_PACK);
|
||||
}
|
||||
IceTrapModels.push_back(0xC9); //Magic bean pack
|
||||
ctx->possibleIceTrapModels.push_back(RG_MAGIC_BEAN_PACK); //Magic bean pack
|
||||
} else {
|
||||
ctx->PlaceItemInLocation(RC_ZR_MAGIC_BEAN_SALESMAN, RG_MAGIC_BEAN, false, true);
|
||||
}
|
||||
|
||||
if (ShuffleMerchants.IsNot(SHUFFLEMERCHANTS_OFF)) {
|
||||
if (!ProgressiveGoronSword) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).IsNot(RO_SHUFFLE_MERCHANTS_OFF)) {
|
||||
if (/*!ProgressiveGoronSword TODO: Implement Progressive Goron Sword*/true) {
|
||||
AddItemToMainPool(RG_GIANTS_KNIFE);
|
||||
}
|
||||
if (BombchusInLogic) {
|
||||
if (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) {
|
||||
AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS);
|
||||
} else {
|
||||
AddItemToMainPool(RG_BOMBCHU_10);
|
||||
@@ -750,7 +751,7 @@ void GenerateItemPool() {
|
||||
ctx->PlaceItemInLocation(RC_WASTELAND_BOMBCHU_SALESMAN, RG_BOMBCHU_10, false, true);
|
||||
}
|
||||
|
||||
if (ShuffleFrogSongRupees) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_FROG_SONG_RUPEES)) {
|
||||
AddItemToMainPool(RG_PURPLE_RUPEE, 5);
|
||||
} else {
|
||||
ctx->PlaceItemInLocation(RC_ZR_FROGS_ZELDAS_LULLABY, RG_PURPLE_RUPEE, false, true);
|
||||
@@ -760,7 +761,7 @@ void GenerateItemPool() {
|
||||
ctx->PlaceItemInLocation(RC_ZR_FROGS_SONG_OF_TIME, RG_PURPLE_RUPEE, false, true);
|
||||
}
|
||||
|
||||
if (ShuffleAdultTradeQuest) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE)) {
|
||||
AddItemToMainPool(RG_POCKET_EGG);
|
||||
AddItemToMainPool(RG_COJIRO);
|
||||
AddItemToMainPool(RG_ODD_MUSHROOM);
|
||||
@@ -783,9 +784,9 @@ void GenerateItemPool() {
|
||||
}
|
||||
AddItemToMainPool(RG_CLAIM_CHECK);
|
||||
|
||||
if (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS)) {
|
||||
AddItemToMainPool(RG_TREASURE_GAME_SMALL_KEY, 6); // 6 individual keys
|
||||
} else if (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK)) {
|
||||
} else if (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK)) {
|
||||
AddItemToMainPool(RG_TREASURE_GAME_SMALL_KEY); // 1 key which will behave as a pack of 6
|
||||
} else {
|
||||
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, false, true);
|
||||
@@ -795,11 +796,11 @@ void GenerateItemPool() {
|
||||
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_TREASURE_GAME_SMALL_KEY, false, true);
|
||||
};
|
||||
|
||||
if (Tokensanity.Is(TOKENSANITY_OFF)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF)) {
|
||||
for (RandomizerCheck loc : ctx->GetLocations(ctx->allLocations, Category::cSkulltula)) {
|
||||
ctx->PlaceItemInLocation(loc, RG_GOLD_SKULLTULA_TOKEN, false, true);
|
||||
}
|
||||
} else if (Tokensanity.Is(TOKENSANITY_DUNGEONS)) {
|
||||
} else if (ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_DUNGEONS)) {
|
||||
for (RandomizerCheck loc : ctx->GetLocations(ctx->allLocations, Category::cSkulltula)) {
|
||||
if (Rando::StaticData::GetLocation(loc)->IsOverworld()) {
|
||||
ctx->PlaceItemInLocation((RandomizerCheck)loc, RG_GOLD_SKULLTULA_TOKEN, false, true);
|
||||
@@ -807,7 +808,7 @@ void GenerateItemPool() {
|
||||
AddItemToMainPool(RG_GOLD_SKULLTULA_TOKEN);
|
||||
}
|
||||
}
|
||||
} else if (Tokensanity.Is(TOKENSANITY_OVERWORLD)) {
|
||||
} else if (ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OVERWORLD)) {
|
||||
for (RandomizerCheck loc : ctx->GetLocations(ctx->allLocations, Category::cSkulltula)) {
|
||||
if (Rando::StaticData::GetLocation(loc)->IsDungeon()) {
|
||||
ctx->PlaceItemInLocation((RandomizerCheck)loc, RG_GOLD_SKULLTULA_TOKEN, false, true);
|
||||
@@ -819,8 +820,8 @@ void GenerateItemPool() {
|
||||
AddItemToMainPool(RG_GOLD_SKULLTULA_TOKEN, 100);
|
||||
}
|
||||
|
||||
if (Shuffle100GSReward) {
|
||||
if (Tokensanity.IsNot(TOKENSANITY_OFF) && ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_100_GS_REWARD)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_TOKENS).IsNot(RO_TOKENSANITY_OFF) && ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
|
||||
AddItemToPool(PendingJunkPool, RG_GOLD_SKULLTULA_TOKEN, 10);
|
||||
}
|
||||
AddItemToMainPool(RG_HUGE_RUPEE);
|
||||
@@ -852,7 +853,7 @@ void GenerateItemPool() {
|
||||
}
|
||||
}
|
||||
|
||||
if (BombchusInLogic) {
|
||||
if (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) {
|
||||
AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS, 5);
|
||||
} else {
|
||||
AddItemToMainPool(RG_BOMBCHU_5);
|
||||
@@ -862,28 +863,28 @@ void GenerateItemPool() {
|
||||
|
||||
//Ice Traps
|
||||
AddItemToMainPool(RG_ICE_TRAP);
|
||||
if (GerudoTrainingGrounds.IsVanilla()) {
|
||||
if (ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUNDS)->IsVanilla()) {
|
||||
AddItemToMainPool(RG_ICE_TRAP);
|
||||
}
|
||||
if (GanonsCastle.IsVanilla()) {
|
||||
if (ctx->GetDungeon(Rando::GANONS_CASTLE)->IsVanilla()) {
|
||||
AddItemToMainPool(RG_ICE_TRAP, 4);
|
||||
}
|
||||
|
||||
//Gerudo Fortress
|
||||
if (GerudoFortress.Is(GERUDOFORTRESS_OPEN)) {
|
||||
if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_OPEN)) {
|
||||
ctx->PlaceItemInLocation(RC_GF_NORTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true);
|
||||
ctx->PlaceItemInLocation(RC_GF_NORTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true);
|
||||
ctx->PlaceItemInLocation(RC_GF_SOUTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true);
|
||||
ctx->PlaceItemInLocation(RC_GF_SOUTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true);
|
||||
} else if (GerudoKeys.IsNot(GERUDOKEYS_VANILLA)) {
|
||||
if (GerudoFortress.Is(GERUDOFORTRESS_FAST)) {
|
||||
} else if (ctx->GetOption(RSK_GERUDO_KEYS).IsNot(RO_GERUDO_KEYS_VANILLA)) {
|
||||
if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_FAST)) {
|
||||
AddItemToMainPool(RG_GERUDO_FORTRESS_SMALL_KEY);
|
||||
ctx->PlaceItemInLocation(RC_GF_NORTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true);
|
||||
ctx->PlaceItemInLocation(RC_GF_SOUTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true);
|
||||
ctx->PlaceItemInLocation(RC_GF_SOUTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true);
|
||||
} else {
|
||||
//Only add key ring if 4 Fortress keys necessary
|
||||
if (RingFortress) {
|
||||
if (ctx->GetOption(RSK_KEYRINGS_GERUDO_FORTRESS)) {
|
||||
AddItemToMainPool(RG_GERUDO_FORTRESS_KEY_RING);
|
||||
//Add junk to make up for missing keys
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
@@ -893,15 +894,15 @@ void GenerateItemPool() {
|
||||
AddItemToMainPool(RG_GERUDO_FORTRESS_SMALL_KEY, 4);
|
||||
}
|
||||
}
|
||||
if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) {
|
||||
if (RingFortress && GerudoFortress.Is(GERUDOFORTRESS_NORMAL)) {
|
||||
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
|
||||
if (ctx->GetOption(RSK_KEYRINGS_GERUDO_FORTRESS) && ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_NORMAL)) {
|
||||
AddItemToPool(PendingJunkPool, RG_GERUDO_FORTRESS_KEY_RING);
|
||||
} else {
|
||||
AddItemToPool(PendingJunkPool, RG_GERUDO_FORTRESS_SMALL_KEY);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (GerudoFortress.Is(GERUDOFORTRESS_FAST)) {
|
||||
if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_FAST)) {
|
||||
ctx->PlaceItemInLocation(RC_GF_NORTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, false, true);
|
||||
ctx->PlaceItemInLocation(RC_GF_NORTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true);
|
||||
ctx->PlaceItemInLocation(RC_GF_SOUTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true);
|
||||
@@ -915,10 +916,10 @@ void GenerateItemPool() {
|
||||
}
|
||||
|
||||
//Gerudo Membership Card
|
||||
if (ShuffleGerudoToken && GerudoFortress.IsNot(GERUDOFORTRESS_OPEN)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD) && ctx->GetOption(RSK_GERUDO_FORTRESS).IsNot(RO_GF_OPEN)) {
|
||||
AddItemToMainPool(RG_GERUDO_MEMBERSHIP_CARD);
|
||||
IceTrapModels.push_back(GI_GERUDO_CARD);
|
||||
} else if (ShuffleGerudoToken) {
|
||||
ctx->possibleIceTrapModels.push_back(RG_GERUDO_MEMBERSHIP_CARD);
|
||||
} else if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
|
||||
AddItemToPool(PendingJunkPool, RG_GERUDO_MEMBERSHIP_CARD);
|
||||
ctx->PlaceItemInLocation(RC_GF_GERUDO_MEMBERSHIP_CARD, RG_ICE_TRAP, false, true);
|
||||
} else {
|
||||
@@ -928,9 +929,9 @@ void GenerateItemPool() {
|
||||
//Keys
|
||||
|
||||
//For key rings, need to add as many junk items as "missing" keys
|
||||
if (KeyRings.IsNot(KEYRINGS_OFF)) {
|
||||
if (ctx->GetOption(RSK_KEYRINGS).IsNot(RO_KEYRINGS_OFF)) {
|
||||
uint8_t ringJunkAmt = 0;
|
||||
for (auto dungeon : dungeonList) {
|
||||
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
if (dungeon->HasKeyRing()) {
|
||||
ringJunkAmt += dungeon->GetSmallKeyCount() - 1;
|
||||
}
|
||||
@@ -940,56 +941,56 @@ void GenerateItemPool() {
|
||||
}
|
||||
}
|
||||
|
||||
if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) {
|
||||
if (ShuffleGerudoToken) {
|
||||
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
|
||||
AddItemToPool(PendingJunkPool, RG_GERUDO_MEMBERSHIP_CARD);
|
||||
}
|
||||
|
||||
//Plentiful small keys
|
||||
if (Keysanity.Is(KEYSANITY_ANYWHERE) || Keysanity.Is(KEYSANITY_ANY_DUNGEON) || Keysanity.Is(KEYSANITY_OVERWORLD)) {
|
||||
if (BottomOfTheWell.HasKeyRing()) {
|
||||
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
|
||||
if (ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->HasKeyRing()) {
|
||||
AddItemToPool(PendingJunkPool, RG_BOTTOM_OF_THE_WELL_KEY_RING);
|
||||
} else {
|
||||
AddItemToPool(PendingJunkPool, RG_BOTTOM_OF_THE_WELL_SMALL_KEY);
|
||||
}
|
||||
if (ForestTemple.HasKeyRing()) {
|
||||
if (ctx->GetDungeon(Rando::FOREST_TEMPLE)->HasKeyRing()) {
|
||||
AddItemToPool(PendingJunkPool, RG_FOREST_TEMPLE_KEY_RING);
|
||||
} else {
|
||||
AddItemToPool(PendingJunkPool, RG_FOREST_TEMPLE_SMALL_KEY);
|
||||
}
|
||||
if (FireTemple.HasKeyRing()) {
|
||||
if (ctx->GetDungeon(Rando::FIRE_TEMPLE)->HasKeyRing()) {
|
||||
AddItemToPool(PendingJunkPool, RG_FIRE_TEMPLE_KEY_RING);
|
||||
} else {
|
||||
AddItemToPool(PendingJunkPool, RG_FIRE_TEMPLE_SMALL_KEY);
|
||||
}
|
||||
if (WaterTemple.HasKeyRing()) {
|
||||
if (ctx->GetDungeon(Rando::WATER_TEMPLE)->HasKeyRing()) {
|
||||
AddItemToPool(PendingJunkPool, RG_WATER_TEMPLE_KEY_RING);
|
||||
} else {
|
||||
AddItemToPool(PendingJunkPool, RG_WATER_TEMPLE_SMALL_KEY);
|
||||
}
|
||||
if (SpiritTemple.HasKeyRing()) {
|
||||
if (ctx->GetDungeon(Rando::SPIRIT_TEMPLE)->HasKeyRing()) {
|
||||
AddItemToPool(PendingJunkPool, RG_SPIRIT_TEMPLE_KEY_RING);
|
||||
} else {
|
||||
AddItemToPool(PendingJunkPool, RG_SPIRIT_TEMPLE_SMALL_KEY);
|
||||
}
|
||||
if (ShadowTemple.HasKeyRing()) {
|
||||
if (ctx->GetDungeon(Rando::SHADOW_TEMPLE)->HasKeyRing()) {
|
||||
AddItemToPool(PendingJunkPool, RG_SHADOW_TEMPLE_KEY_RING);
|
||||
} else {
|
||||
AddItemToPool(PendingJunkPool, RG_SHADOW_TEMPLE_SMALL_KEY);
|
||||
}
|
||||
if (GerudoTrainingGrounds.HasKeyRing()) {
|
||||
if (ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUNDS)->HasKeyRing()) {
|
||||
AddItemToPool(PendingJunkPool, RG_GERUDO_TRAINING_GROUNDS_KEY_RING);
|
||||
} else {
|
||||
AddItemToPool(PendingJunkPool, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY);
|
||||
}
|
||||
if (GanonsCastle.HasKeyRing()) {
|
||||
if (ctx->GetDungeon(Rando::GANONS_CASTLE)->HasKeyRing()) {
|
||||
AddItemToPool(PendingJunkPool, RG_GANONS_CASTLE_KEY_RING);
|
||||
} else {
|
||||
AddItemToPool(PendingJunkPool, RG_GANONS_CASTLE_SMALL_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
if (BossKeysanity.Is(BOSSKEYSANITY_ANYWHERE) || BossKeysanity.Is(BOSSKEYSANITY_ANY_DUNGEON) || BossKeysanity.Is(BOSSKEYSANITY_OVERWORLD)) {
|
||||
if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) || ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
|
||||
AddItemToPool(PendingJunkPool, RG_FOREST_TEMPLE_BOSS_KEY);
|
||||
AddItemToPool(PendingJunkPool, RG_FIRE_TEMPLE_BOSS_KEY);
|
||||
AddItemToPool(PendingJunkPool, RG_WATER_TEMPLE_BOSS_KEY);
|
||||
@@ -997,36 +998,36 @@ void GenerateItemPool() {
|
||||
AddItemToPool(PendingJunkPool, RG_SHADOW_TEMPLE_BOSS_KEY);
|
||||
}
|
||||
|
||||
if (GanonsBossKey.Is(GANONSBOSSKEY_ANYWHERE) || GanonsBossKey.Is(GANONSBOSSKEY_ANY_DUNGEON) || GanonsBossKey.Is(GANONSBOSSKEY_OVERWORLD)) {
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANYWHERE) || ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON) || ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) {
|
||||
AddItemToPool(PendingJunkPool, RG_GANONS_CASTLE_BOSS_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
//Shopsanity
|
||||
if (Settings::Shopsanity.Is(SHOPSANITY_OFF) || Settings::Shopsanity.Is(SHOPSANITY_ZERO)) {
|
||||
if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF) || ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_ZERO_ITEMS)) {
|
||||
AddItemsToPool(ItemPool, normalRupees);
|
||||
} else { //Shopsanity 1-4, random
|
||||
AddItemsToPool(ItemPool, shopsanityRupees); //Shopsanity gets extra large rupees
|
||||
}
|
||||
|
||||
//Scrubsanity
|
||||
if (Settings::Scrubsanity.IsNot(SCRUBSANITY_OFF)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).IsNot(RO_SCRUBS_OFF)) {
|
||||
//Deku Tree
|
||||
if (DekuTree.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::DEKU_TREE)->IsMQ()) {
|
||||
AddItemToMainPool(RG_DEKU_SHIELD);
|
||||
}
|
||||
|
||||
//Dodongos Cavern
|
||||
AddItemToMainPool(RG_DEKU_STICK_1);
|
||||
AddItemToMainPool(RG_DEKU_SHIELD);
|
||||
if (DodongosCavern.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::DODONGOS_CAVERN)->IsMQ()) {
|
||||
AddItemToMainPool(RG_RECOVERY_HEART);
|
||||
} else {
|
||||
AddItemToMainPool(RG_DEKU_NUTS_5);
|
||||
}
|
||||
|
||||
//Jabu Jabus Belly
|
||||
if (JabuJabusBelly.IsVanilla()) {
|
||||
if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsVanilla()) {
|
||||
AddItemToMainPool(RG_DEKU_NUTS_5);
|
||||
}
|
||||
|
||||
@@ -1034,7 +1035,7 @@ void GenerateItemPool() {
|
||||
AddItemToMainPool(RG_BOMBS_5);
|
||||
AddItemToMainPool(RG_RECOVERY_HEART);
|
||||
AddItemToMainPool(RG_BLUE_RUPEE);
|
||||
if (GanonsCastle.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::GANONS_CASTLE)->IsMQ()) {
|
||||
AddItemToMainPool(RG_DEKU_NUTS_5);
|
||||
}
|
||||
|
||||
@@ -1057,55 +1058,55 @@ void GenerateItemPool() {
|
||||
AddItemsToPool(ItemPool, dungeonRewards);
|
||||
|
||||
//Dungeon pools
|
||||
if (DekuTree.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::DEKU_TREE)->IsMQ()) {
|
||||
AddItemsToPool(ItemPool, DT_MQ);
|
||||
} else {
|
||||
AddItemsToPool(ItemPool, DT_Vanilla);
|
||||
}
|
||||
if (DodongosCavern.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::DODONGOS_CAVERN)->IsMQ()) {
|
||||
AddItemsToPool(ItemPool, DC_MQ);
|
||||
} else {
|
||||
AddItemsToPool(ItemPool, DC_Vanilla);
|
||||
}
|
||||
if (JabuJabusBelly.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsMQ()) {
|
||||
AddItemsToPool(ItemPool, JB_MQ);
|
||||
}
|
||||
if (ForestTemple.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::FOREST_TEMPLE)->IsMQ()) {
|
||||
AddItemsToPool(ItemPool, FoT_MQ);
|
||||
} else {
|
||||
AddItemsToPool(ItemPool, FoT_Vanilla);
|
||||
}
|
||||
if (FireTemple.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsMQ()) {
|
||||
AddItemsToPool(ItemPool, FiT_MQ);
|
||||
} else {
|
||||
AddItemsToPool(ItemPool, FiT_Vanilla);
|
||||
}
|
||||
if (SpiritTemple.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::SPIRIT_TEMPLE)->IsMQ()) {
|
||||
AddItemsToPool(ItemPool, SpT_MQ);
|
||||
} else {
|
||||
AddItemsToPool(ItemPool, SpT_Vanilla);
|
||||
}
|
||||
if (ShadowTemple.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::SHADOW_TEMPLE)->IsMQ()) {
|
||||
AddItemsToPool(ItemPool, ShT_MQ);
|
||||
} else {
|
||||
AddItemsToPool(ItemPool, ShT_Vanilla);
|
||||
}
|
||||
if (BottomOfTheWell.IsVanilla()) {
|
||||
if (ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla()) {
|
||||
AddItemsToPool(ItemPool, BW_Vanilla);
|
||||
}
|
||||
if (GerudoTrainingGrounds.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUNDS)->IsMQ()) {
|
||||
AddItemsToPool(ItemPool, GTG_MQ);
|
||||
} else {
|
||||
AddItemsToPool(ItemPool, GTG_Vanilla);
|
||||
}
|
||||
if (GanonsCastle.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::GANONS_CASTLE)->IsMQ()) {
|
||||
AddItemsToPool(ItemPool, GC_MQ);
|
||||
} else {
|
||||
AddItemsToPool(ItemPool, GC_Vanilla);
|
||||
}
|
||||
|
||||
uint8_t rutoBottles = 1;
|
||||
if (ZorasFountain.Is(ZORASFOUNTAIN_OPEN)) {
|
||||
if (ctx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN)) {
|
||||
rutoBottles = 0;
|
||||
}
|
||||
|
||||
@@ -1113,11 +1114,11 @@ void GenerateItemPool() {
|
||||
uint8_t bottleCount = 4;
|
||||
std::vector<RandomizerGet> bottles;
|
||||
bottles.assign(normalBottles.begin(), normalBottles.end());
|
||||
IceTrapModels.push_back(
|
||||
Rando::StaticData::RetrieveItem(RandomElement(bottles)).GetItemID()); // Get one random bottle type for ice traps
|
||||
ctx->possibleIceTrapModels.push_back(
|
||||
Rando::StaticData::RetrieveItem(RandomElement(bottles)).GetRandomizerGet()); // Get one random bottle type for ice traps
|
||||
for (uint8_t i = 0; i < bottleCount; i++) {
|
||||
if (i >= rutoBottles) {
|
||||
if ((i == bottleCount - 1) && ShuffleMerchants.IsNot(SHUFFLEMERCHANTS_OFF)) {
|
||||
if ((i == bottleCount - 1) && ctx->GetOption(RSK_SHUFFLE_MERCHANTS).IsNot(RO_SHUFFLE_MERCHANTS_OFF)) {
|
||||
AddItemToMainPool(RG_BOTTLE_WITH_BLUE_POTION);
|
||||
} else {
|
||||
AddRandomBottle(bottles);
|
||||
@@ -1129,7 +1130,7 @@ void GenerateItemPool() {
|
||||
|
||||
//add extra songs only if song shuffle is anywhere
|
||||
AddItemsToPool(ItemPool, songList);
|
||||
if (ShuffleSongs.Is(SONGSHUFFLE_ANYWHERE) && ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE) && ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
|
||||
AddItemsToPool(PendingJunkPool, songList);
|
||||
}
|
||||
|
||||
@@ -1140,10 +1141,10 @@ void GenerateItemPool() {
|
||||
| advancement items that haven't been placed yet for placing higher priority
|
||||
| items like stones/medallions.*/
|
||||
|
||||
if (MapsAndCompasses.Is(MAPSANDCOMPASSES_VANILLA)) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_VANILLA)) {
|
||||
PlaceVanillaMapsAndCompasses();
|
||||
} else {
|
||||
for (auto dungeon : dungeonList) {
|
||||
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
if (dungeon->GetMap() != RG_NONE) {
|
||||
AddItemToMainPool(dungeon->GetMap());
|
||||
}
|
||||
@@ -1154,11 +1155,11 @@ void GenerateItemPool() {
|
||||
}
|
||||
}
|
||||
|
||||
if (Keysanity.Is(KEYSANITY_VANILLA)) {
|
||||
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA)) {
|
||||
PlaceVanillaSmallKeys();
|
||||
} else {
|
||||
for (auto dungeon : dungeonList) {
|
||||
if (dungeon->HasKeyRing() && Keysanity.IsNot(KEYSANITY_START_WITH)) {
|
||||
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
if (dungeon->HasKeyRing() && ctx->GetOption(RSK_KEYSANITY).IsNot(RO_DUNGEON_ITEM_LOC_STARTWITH)) {
|
||||
AddItemToMainPool(dungeon->GetKeyRing());
|
||||
} else {
|
||||
if (dungeon->GetSmallKeyCount() > 0) {
|
||||
@@ -1168,7 +1169,7 @@ void GenerateItemPool() {
|
||||
}
|
||||
}
|
||||
|
||||
if (BossKeysanity.Is(BOSSKEYSANITY_VANILLA)) {
|
||||
if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA)) {
|
||||
PlaceVanillaBossKeys();
|
||||
} else {
|
||||
AddItemToMainPool(RG_FOREST_TEMPLE_BOSS_KEY);
|
||||
@@ -1178,54 +1179,54 @@ void GenerateItemPool() {
|
||||
AddItemToMainPool(RG_SHADOW_TEMPLE_BOSS_KEY);
|
||||
}
|
||||
|
||||
if (GanonsBossKey.Is(GANONSBOSSKEY_FINAL_GS_REWARD)) {
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) {
|
||||
ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_GANONS_CASTLE_BOSS_KEY);
|
||||
} else if (GanonsBossKey.Value<uint8_t>() >= GANONSBOSSKEY_LACS_VANILLA && GanonsBossKey.IsNot(GANONSBOSSKEY_TRIFORCE_HUNT)) {
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Value<uint8_t>() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
|
||||
ctx->PlaceItemInLocation(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_GANONS_CASTLE_BOSS_KEY);
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA)) {
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) {
|
||||
ctx->PlaceItemInLocation(RC_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY);
|
||||
} else {
|
||||
AddItemToMainPool(RG_GANONS_CASTLE_BOSS_KEY);
|
||||
}
|
||||
|
||||
if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) {
|
||||
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
|
||||
AddItemsToPool(ItemPool, easyItems);
|
||||
} else {
|
||||
AddItemsToPool(ItemPool, normalItems);
|
||||
}
|
||||
|
||||
if (!ShuffleKokiriSword) {
|
||||
if (!ctx->GetOption(RSK_SHUFFLE_KOKIRI_SWORD)) {
|
||||
ReplaceMaxItem(RG_KOKIRI_SWORD, 0);
|
||||
}
|
||||
|
||||
if (!ShuffleMasterSword) {
|
||||
if (!ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) {
|
||||
ReplaceMaxItem(RG_MASTER_SWORD, 0);
|
||||
}
|
||||
|
||||
if (ProgressiveGoronSword) {
|
||||
if (/*ProgressiveGoronSword TODO: Implement Setting*/false) {
|
||||
ReplaceMaxItem(RG_BIGGORON_SWORD, 0);
|
||||
AddItemToMainPool(RG_PROGRESSIVE_GORONSWORD, 2);
|
||||
IceTrapModels.push_back(0xD4); // Progressive Goron Sword
|
||||
ctx->possibleIceTrapModels.push_back(RG_PROGRESSIVE_GORONSWORD); // Progressive Goron Sword
|
||||
} else {
|
||||
IceTrapModels.push_back(GI_SWORD_BGS);
|
||||
ctx->possibleIceTrapModels.push_back(RG_BIGGORON_SWORD);
|
||||
}
|
||||
|
||||
//Replace ice traps with junk from the pending junk pool if necessary
|
||||
if (IceTrapValue.Is(ICETRAPS_OFF)) {
|
||||
if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_OFF)) {
|
||||
ReplaceMaxItem(RG_ICE_TRAP, 0);
|
||||
}
|
||||
//Replace all junk items with ice traps for onslaught mode
|
||||
else if (IceTrapValue.Is(ICETRAPS_ONSLAUGHT)) {
|
||||
else if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_ONSLAUGHT)) {
|
||||
for (uint8_t i = 0; i < JunkPoolItems.size() - 3; i++) { // -3 Omits Huge Rupees and Deku Nuts 10
|
||||
ReplaceMaxItem(JunkPoolItems[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (ItemPoolValue.Is(ITEMPOOL_SCARCE)) {
|
||||
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_SCARCE)) {
|
||||
SetScarceItemPool();
|
||||
} else if (ItemPoolValue.Is(ITEMPOOL_MINIMAL)) {
|
||||
} else if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_MINIMAL)) {
|
||||
SetMinimalItemPool();
|
||||
} else if (RemoveDoubleDefense) {
|
||||
} else if (/*RemoveDoubleDefense TODO: Implement setting*/ false) {
|
||||
ReplaceMaxItem(RG_DOUBLE_DEFENSE, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,4 +14,3 @@ void GenerateItemPool();
|
||||
void AddJunk();
|
||||
|
||||
extern std::vector<RandomizerGet> ItemPool;
|
||||
extern std::vector<uint8_t> IceTrapModels;
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
#include "location_access.hpp"
|
||||
|
||||
#include "dungeon.hpp"
|
||||
#include "../dungeon.h"
|
||||
#include "../static_data.h"
|
||||
#include "../context.h"
|
||||
#include "item_pool.hpp"
|
||||
#include "logic.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "trial.hpp"
|
||||
#include "entrance.hpp"
|
||||
#include "../trial.h"
|
||||
#include "../entrance.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
//generic grotto event list
|
||||
std::vector<EventAccess> grottoEvents = {
|
||||
@@ -80,7 +78,8 @@ bool LocationAccess::CanBuy() const {
|
||||
}
|
||||
// If bombchus in logic, need to have found chus to buy; if not just need bomb bag
|
||||
else if (placed == RG_BUY_BOMBCHU_10 || placed == RG_BUY_BOMBCHU_20) {
|
||||
OtherCondition = (!BombchusInLogic && Bombs) || (BombchusInLogic && FoundBombchus);
|
||||
OtherCondition =
|
||||
(!ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && Bombs) || (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && FoundBombchus);
|
||||
}
|
||||
|
||||
return SufficientWallet && OtherCondition;
|
||||
@@ -91,7 +90,7 @@ Area::Area(std::string regionName_, std::string scene_, RandomizerHintTextKey hi
|
||||
bool timePass_,
|
||||
std::vector<EventAccess> events_,
|
||||
std::vector<LocationAccess> locations_,
|
||||
std::list<Entrance> exits_)
|
||||
std::list<Rando::Entrance> exits_)
|
||||
: regionName(std::move(regionName_)),
|
||||
scene(std::move(scene_)),
|
||||
hintKey(hintKey_),
|
||||
@@ -139,13 +138,13 @@ bool Area::UpdateEvents(SearchMode mode) {
|
||||
}
|
||||
|
||||
void Area::AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition) {
|
||||
Entrance newExit = Entrance(newExitKey, {condition});
|
||||
Rando::Entrance newExit = Rando::Entrance(newExitKey, {condition});
|
||||
newExit.SetParentRegion(parentKey);
|
||||
exits.push_front(newExit);
|
||||
}
|
||||
|
||||
//The exit will be completely removed from this area
|
||||
void Area::RemoveExit(Entrance* exitToRemove) {
|
||||
void Area::RemoveExit(Rando::Entrance* exitToRemove) {
|
||||
exits.remove_if([exitToRemove](const auto exit){return &exit == exitToRemove;});
|
||||
}
|
||||
|
||||
@@ -158,7 +157,7 @@ void Area::SetAsPrimary(RandomizerRegion exitToBePrimary) {
|
||||
}
|
||||
}
|
||||
|
||||
Entrance* Area::GetExit(RandomizerRegion exitToReturn) {
|
||||
Rando::Entrance* Area::GetExit(RandomizerRegion exitToReturn) {
|
||||
for (auto& exit : exits) {
|
||||
if (exit.Getuint32_t() == exitToReturn) {
|
||||
return &exit;
|
||||
@@ -200,7 +199,7 @@ bool Area::CheckAllAccess(const RandomizerRegion exitKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Entrance& exit : exits) {
|
||||
for (Rando::Entrance& exit : exits) {
|
||||
if (exit.GetConnectedRegionKey() == exitKey) {
|
||||
return exit.CheckConditionAtAgeTime(Logic::IsChild, Logic::AtDay) &&
|
||||
exit.CheckConditionAtAgeTime(Logic::IsChild, Logic::AtNight) &&
|
||||
@@ -248,9 +247,11 @@ bool HasAccessTo(const RandomizerRegion area) {
|
||||
return areaTable[area].HasAccess();
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Rando::Context> randoCtx;
|
||||
|
||||
void AreaTable_Init() {
|
||||
using namespace Rando;
|
||||
randoCtx = Context::GetInstance();
|
||||
//Clear the array from any previous playthrough attempts. This is important so that
|
||||
//locations which appear in both MQ and Vanilla dungeons don't get set in both areas.
|
||||
areaTable.fill(Area("Invalid Area", "Invalid Area", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {}));
|
||||
@@ -380,18 +381,19 @@ namespace Areas {
|
||||
}
|
||||
|
||||
void AccessReset() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (const RandomizerRegion area : GetAllAreas()) {
|
||||
AreaTable(area)->ResetVariables();
|
||||
}
|
||||
|
||||
if(Settings::HasNightStart) {
|
||||
if(Settings::ResolvedStartingAge == AGE_CHILD) {
|
||||
if(/*Settings::HasNightStart TODO:: Randomize Starting Time*/ false) {
|
||||
if(ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) {
|
||||
AreaTable(RR_ROOT)->childNight = true;
|
||||
} else {
|
||||
AreaTable(RR_ROOT)->adultNight = true;
|
||||
}
|
||||
} else {
|
||||
if(Settings::ResolvedStartingAge == AGE_CHILD) {
|
||||
if(ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) {
|
||||
AreaTable(RR_ROOT)->childDay = true;
|
||||
} else {
|
||||
AreaTable(RR_ROOT)->adultDay = true;
|
||||
@@ -401,6 +403,7 @@ namespace Areas {
|
||||
|
||||
//Reset exits and clear items from locations
|
||||
void ResetAllLocations() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (const RandomizerRegion area : GetAllAreas()) {
|
||||
AreaTable(area)->ResetVariables();
|
||||
//Erase item from every location in this exit
|
||||
@@ -410,14 +413,14 @@ namespace Areas {
|
||||
}
|
||||
}
|
||||
|
||||
if(Settings::HasNightStart) {
|
||||
if(Settings::ResolvedStartingAge == AGE_CHILD) {
|
||||
if (/*Settings::HasNightStart TODO:: Randomize Starting Time*/ false) {
|
||||
if(ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) {
|
||||
AreaTable(RR_ROOT)->childNight = true;
|
||||
} else {
|
||||
AreaTable(RR_ROOT)->adultNight = true;
|
||||
}
|
||||
} else {
|
||||
if(Settings::ResolvedStartingAge == AGE_CHILD) {
|
||||
} else {
|
||||
if(ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) {
|
||||
AreaTable(RR_ROOT)->childDay = true;
|
||||
} else {
|
||||
AreaTable(RR_ROOT)->adultDay = true;
|
||||
@@ -428,7 +431,7 @@ namespace Areas {
|
||||
bool HasTimePassAccess(uint8_t age) {
|
||||
for (const RandomizerRegion areaKey : GetAllAreas()) {
|
||||
auto area = AreaTable(areaKey);
|
||||
if (area->timePass && ((age == AGE_CHILD && area->Child()) || (age == AGE_ADULT && area->Adult()))) {
|
||||
if (area->timePass && ((age == RO_AGE_CHILD && area->Child()) || (age == RO_AGE_ADULT && area->Adult()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -495,11 +498,11 @@ Area* AreaTable(const RandomizerRegion areaKey) {
|
||||
}
|
||||
|
||||
//Retrieve all the shuffable entrances of a specific type
|
||||
std::vector<Entrance*> GetShuffleableEntrances(EntranceType type, bool onlyPrimary /*= true*/) {
|
||||
std::vector<Entrance*> entrancesToShuffle = {};
|
||||
std::vector<Rando::Entrance*> GetShuffleableEntrances(Rando::EntranceType type, bool onlyPrimary /*= true*/) {
|
||||
std::vector<Rando::Entrance*> entrancesToShuffle = {};
|
||||
for (RandomizerRegion area : Areas::GetAllAreas()) {
|
||||
for (auto& exit: AreaTable(area)->exits) {
|
||||
if ((exit.GetType() == type || type == EntranceType::All) && (exit.IsPrimary() || !onlyPrimary) && exit.GetType() != EntranceType::None) {
|
||||
if ((exit.GetType() == type || type == Rando::EntranceType::All) && (exit.IsPrimary() || !onlyPrimary) && exit.GetType() != Rando::EntranceType::None) {
|
||||
entrancesToShuffle.push_back(&exit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,13 @@
|
||||
#include "logic.hpp"
|
||||
#include "hint_list.hpp"
|
||||
#include "fill.hpp"
|
||||
#include "../context.h"
|
||||
|
||||
typedef bool (*ConditionFn)();
|
||||
|
||||
// I hate this but every alternative I can think of right now is worse
|
||||
extern std::shared_ptr<Rando::Context> randoCtx;
|
||||
|
||||
class EventAccess {
|
||||
public:
|
||||
|
||||
@@ -23,11 +27,12 @@ public:
|
||||
}
|
||||
|
||||
bool ConditionsMet() const {
|
||||
if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
|
||||
return true;
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHLESS)) {
|
||||
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
|
||||
return conditions_met[0]();
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHED)) {
|
||||
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) {
|
||||
if (conditions_met[0]()) {
|
||||
return true;
|
||||
} else if (conditions_met[1] != NULL) {
|
||||
@@ -77,11 +82,12 @@ public:
|
||||
}
|
||||
|
||||
bool GetConditionsMet() const {
|
||||
if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
|
||||
return true;
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHLESS)) {
|
||||
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
|
||||
return conditions_met[0]();
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHED)) {
|
||||
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) {
|
||||
if (conditions_met[0]()) {
|
||||
return true;
|
||||
} else if (conditions_met[1] != NULL) {
|
||||
@@ -107,8 +113,10 @@ protected:
|
||||
bool CanBuy() const;
|
||||
};
|
||||
|
||||
class Entrance;
|
||||
enum class EntranceType;
|
||||
namespace Rando {
|
||||
class Entrance;
|
||||
enum class EntranceType;
|
||||
}
|
||||
|
||||
class Area {
|
||||
public:
|
||||
@@ -117,7 +125,7 @@ public:
|
||||
bool timePass_,
|
||||
std::vector<EventAccess> events_,
|
||||
std::vector<LocationAccess> locations_,
|
||||
std::list<Entrance> exits_);
|
||||
std::list<Rando::Entrance> exits_);
|
||||
~Area();
|
||||
|
||||
std::string regionName;
|
||||
@@ -126,8 +134,8 @@ public:
|
||||
bool timePass;
|
||||
std::vector<EventAccess> events;
|
||||
std::vector<LocationAccess> locations;
|
||||
std::list<Entrance> exits;
|
||||
std::list<Entrance*> entrances;
|
||||
std::list<Rando::Entrance> exits;
|
||||
std::list<Rando::Entrance*> entrances;
|
||||
//^ The above exits are now stored in a list instead of a vector because
|
||||
//the entrance randomization algorithm plays around with pointers to these
|
||||
//entrances a lot. By putting the entrances in a list, we don't have to
|
||||
@@ -144,11 +152,11 @@ public:
|
||||
|
||||
void AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition);
|
||||
|
||||
void RemoveExit(Entrance* exitToRemove);
|
||||
void RemoveExit(Rando::Entrance* exitToRemove);
|
||||
|
||||
void SetAsPrimary(RandomizerRegion exitToBePrimary);
|
||||
|
||||
Entrance* GetExit(RandomizerRegion exit);
|
||||
Rando::Entrance* GetExit(RandomizerRegion exit);
|
||||
|
||||
bool Child() const {
|
||||
return childDay || childNight;
|
||||
@@ -240,7 +248,7 @@ namespace Areas {
|
||||
|
||||
void AreaTable_Init();
|
||||
Area* AreaTable(const RandomizerRegion areaKey);
|
||||
std::vector<Entrance*> GetShuffleableEntrances(EntranceType type, bool onlyPrimary = true);
|
||||
std::vector<Rando::Entrance*> GetShuffleableEntrances(Rando::EntranceType type, bool onlyPrimary = true);
|
||||
|
||||
// Overworld
|
||||
void AreaTable_Init_LostWoods();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_BottomOfTheWell() {
|
||||
/*--------------------------
|
||||
@@ -12,38 +12,38 @@ void AreaTable_Init_BottomOfTheWell() {
|
||||
---------------------------*/
|
||||
areaTable[RR_BOTTOM_OF_THE_WELL_ENTRYWAY] = Area("Bottom of the Well Entryway", "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MAIN_AREA, {[]{return Dungeon::BottomOfTheWell.IsVanilla() && IsChild && (CanChildAttack || Nuts);}}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, {[]{return Dungeon::BottomOfTheWell.IsMQ() && IsChild;}}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MAIN_AREA, {[]{return randoCtx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla() && IsChild && (CanChildAttack || Nuts);}}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, {[]{return randoCtx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsMQ() && IsChild;}}),
|
||||
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::BottomOfTheWell.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla()) {
|
||||
areaTable[RR_BOTTOM_OF_THE_WELL_MAIN_AREA] = Area("Bottom of the Well Main Area", "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&StickPot, {[]{return true;}}),
|
||||
EventAccess(&NutPot, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, {[]{return HasExplosives;}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, {[]{return (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, {[]{return Sticks || CanUse(RG_DINS_FIRE);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, {[]{return CanPlay(ZeldasLullaby) && (KokiriSword || (Sticks && LogicChildDeadhand));}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, {[]{return CanPlay(ZeldasLullaby) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, {[]{return CanPlay(ZeldasLullaby) && (KokiriSword || (Sticks && randoCtx->GetTrickOption(RT_BOTW_CHILD_DEADHAND)));}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, {[]{return CanPlay(ZeldasLullaby) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, {[]{return HasExplosives || (((SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH))) || CanUse(RG_DINS_FIRE) || (Sticks && LogicBotwBasement)) && GoronBracelet);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, {[]{return Boomerang && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, {[]{return Boomerang && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && Boomerang;}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, {[]{return HasExplosives || (((SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH))) || CanUse(RG_DINS_FIRE) || (Sticks && randoCtx->GetTrickOption(RT_BOTW_BASEMENT))) && GoronBracelet);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, {[]{return Boomerang && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH)) && SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, {[]{return Boomerang && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH)) && SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH)) && Boomerang;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}),
|
||||
@@ -53,21 +53,21 @@ void AreaTable_Init_BottomOfTheWell() {
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::BottomOfTheWell.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsMQ()) {
|
||||
areaTable[RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER] = Area("Bottom of the Well MQ Perimeter", "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
//EventAccess(&WallFairy, {[]{return WallFairy || Slingshot;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, {[]{return KokiriSword || (Sticks && LogicChildDeadhand);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, {[]{return HasExplosives || (LogicBotwMQDeadHandKey && Boomerang);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, {[]{return KokiriSword || (Sticks && randoCtx->GetTrickOption(RT_BOTW_CHILD_DEADHAND));}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, {[]{return HasExplosives || (randoCtx->GetTrickOption(RT_BOTW_MQ_DEADHAND_KEY) && Boomerang);}}),
|
||||
//Trick: HasExplosives || (LogicBotWMQDeadHandKey && Boomerang)
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, {[]{return CanChildAttack;}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, {[]{return CanChildAttack && SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, {[]{return CanPlay(ZeldasLullaby) || (LogicBotwMQPits && HasExplosives);}}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, {[]{return CanPlay(ZeldasLullaby) || (randoCtx->GetTrickOption(RT_BOTW_MQ_PITS) && HasExplosives);}}),
|
||||
//Trick: CanPlay(ZeldasLullaby) || (LogicBotWMQPits && HasExplosives)
|
||||
});
|
||||
|
||||
@@ -76,7 +76,7 @@ void AreaTable_Init_BottomOfTheWell() {
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, {[]{return HasExplosives && SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, {[]{return true;}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, {[]{return CanChildAttack && (LogicBotwMQPits || HasExplosives);}}),
|
||||
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, {[]{return CanChildAttack && (randoCtx->GetTrickOption(RT_BOTW_MQ_PITS) || HasExplosives);}}),
|
||||
//Trick: CanChildAttack && (LogicBotWMQPits || HasExplosives)
|
||||
}, {
|
||||
//Exits
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../../entrance.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_CastleTown() {
|
||||
areaTable[RR_MARKET_ENTRANCE] = Area("Market Entrance", "Market Entrance", RHT_THE_MARKET, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
@@ -58,7 +58,7 @@ void AreaTable_Init_CastleTown() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_TOT_ENTRANCE, {[]{return true;}}),
|
||||
Entrance(RR_TOT_BEYOND_DOOR_OF_TIME, {[]{return OpenDoorOfTime.Is(OPENDOOROFTIME_OPEN) || (CanPlay(SongOfTime) && (OpenDoorOfTime.Is(OPENDOOROFTIME_SONGONLY) || (HasAllStones && OcarinaOfTime)));}}),
|
||||
Entrance(RR_TOT_BEYOND_DOOR_OF_TIME, {[]{return randoCtx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN) || (CanPlay(SongOfTime) && (randoCtx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_SONGONLY) || (HasAllStones && OcarinaOfTime)));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_TOT_BEYOND_DOOR_OF_TIME] = Area("Beyond Door of Time", "Beyond Door of Time", RHT_TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {
|
||||
@@ -94,7 +94,7 @@ void AreaTable_Init_CastleTown() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}),
|
||||
Entrance(RR_HC_GARDEN, {[]{return WeirdEgg || !ShuffleWeirdEgg;}}),
|
||||
Entrance(RR_HC_GARDEN, {[]{return WeirdEgg || !randoCtx->GetOption(RSK_SHUFFLE_WEIRD_EGG);}}),
|
||||
Entrance(RR_HC_GREAT_FAIRY_FOUNTAIN, {[]{return CanBlastOrSmash;}}),
|
||||
Entrance(RR_HC_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
|
||||
});
|
||||
@@ -125,7 +125,7 @@ void AreaTable_Init_CastleTown() {
|
||||
EventAccess(&WanderingBugs, {[]{return WanderingBugs || CanBlastOrSmash;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_HC_GS_STORMS_GROTTO, {[]{return (CanBlastOrSmash && HookshotOrBoomerang) || (Boomerang && LogicCastleStormsGS);}}),
|
||||
LocationAccess(RC_HC_GS_STORMS_GROTTO, {[]{return (CanBlastOrSmash && HookshotOrBoomerang) || (Boomerang && randoCtx->GetTrickOption(RT_HC_STORMS_GS));}}),
|
||||
LocationAccess(RC_HC_STORMS_GROTTO_GOSSIP_STONE, {[]{return CanBlastOrSmash;}}),
|
||||
}, {
|
||||
//Exits
|
||||
@@ -192,8 +192,8 @@ void AreaTable_Init_CastleTown() {
|
||||
|
||||
areaTable[RR_MARKET_MASK_SHOP] = Area("Market Mask Shop", "Market Mask Shop", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&SkullMask, {[]{return SkullMask || (ZeldasLetter && (CompleteMaskQuest || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}}),
|
||||
EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (CompleteMaskQuest || (ChildCanAccess(RR_THE_LOST_WOODS) && CanPlay(SariasSong) && AreaTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && HasAllStones)));}}),
|
||||
EventAccess(&SkullMask, {[]{return SkullMask || (ZeldasLetter && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}}),
|
||||
EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && CanPlay(SariasSong) && AreaTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && HasAllStones)));}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_THE_MARKET, {[]{return true;}}),
|
||||
@@ -235,12 +235,12 @@ void AreaTable_Init_CastleTown() {
|
||||
areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "Market Treasure Chest Game", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GREG_HINT, {[]{return true;}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1));}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1));}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME));}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME));}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME));}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME));}}),
|
||||
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_THE_MARKET, {[]{return true;}}),
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../../entrance.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_DeathMountain() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
areaTable[RR_DEATH_MOUNTAIN_TRAIL] = Area("Death Mountain", "Death Mountain", RHT_DEATH_MOUNTAIN_TRAIL, DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && CanPlay(SongOfStorms) && (HasExplosives || GoronBracelet));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_DMT_CHEST, {[]{return CanBlastOrSmash || (LogicDMTBombable && IsChild && GoronBracelet);}}),
|
||||
LocationAccess(RC_DMT_CHEST, {[]{return CanBlastOrSmash || (randoCtx->GetTrickOption(RT_DMT_BOMBABLE) && IsChild && GoronBracelet);}}),
|
||||
LocationAccess(RC_DMT_FREESTANDING_POH, {[]{return CanTakeDamage || CanUse(RG_HOVER_BOOTS) || (IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && (HasExplosives || GoronBracelet));}}),
|
||||
LocationAccess(RC_DMT_GS_BEAN_PATCH, {[]{return CanPlantBugs && (HasExplosives || GoronBracelet || (LogicDMTSoilGS && (CanTakeDamage || CanUse(RG_HOVER_BOOTS)) && CanUse(RG_BOOMERANG)));}}),
|
||||
LocationAccess(RC_DMT_GS_BEAN_PATCH, {[]{return CanPlantBugs && (HasExplosives || GoronBracelet || (randoCtx->GetTrickOption(RT_DMT_SOIL_GS) && (CanTakeDamage || CanUse(RG_HOVER_BOOTS)) && CanUse(RG_BOOMERANG)));}}),
|
||||
LocationAccess(RC_DMT_GS_NEAR_KAK, {[]{return CanBlastOrSmash;}}),
|
||||
LocationAccess(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, {[]{return IsAdult && AtNight && (CanUse(RG_MEGATON_HAMMER) || (LogicDMTGSLowerHookshot && CanUse(RG_HOOKSHOT)) || (LogicDMTGSLowerBean && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL)) || (LogicDMTGSLowerHovers && CanUse(RG_HOVER_BOOTS)) || LogicDMTGSLowerJS) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, {[]{return IsAdult && AtNight && (CanUse(RG_MEGATON_HAMMER) || (randoCtx->GetTrickOption(RT_DMT_HOOKSHOT_LOWER_GS) && CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL)) || (randoCtx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && CanUse(RG_HOVER_BOOTS)) || randoCtx->GetTrickOption(RT_DMT_JS_LOWER_GS)) && CanGetNightTimeGS;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_KAK_BEHIND_GATE, {[]{return true;}}),
|
||||
Entrance(RR_GORON_CITY, {[]{return true;}}),
|
||||
Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return Here(RR_DEATH_MOUNTAIN_TRAIL, []{return CanBlastOrSmash;}) || (IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && GoronBracelet) || (HoverBoots && LogicDMTClimbHovers)));}}),
|
||||
Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return Here(RR_DEATH_MOUNTAIN_TRAIL, []{return CanBlastOrSmash;}) || (IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && GoronBracelet) || (HoverBoots && randoCtx->GetTrickOption(RT_DMT_CLIMB_HOVERS))));}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, {[]{return HasExplosives || GoronBracelet || IsAdult;}}),
|
||||
Entrance(RR_DMT_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
|
||||
});
|
||||
@@ -35,7 +36,7 @@ void AreaTable_Init_DeathMountain() {
|
||||
LocationAccess(RC_DMT_TRADE_BROKEN_SWORD, {[]{return IsAdult && BrokenSword;}}),
|
||||
LocationAccess(RC_DMT_TRADE_EYEDROPS, {[]{return IsAdult && Eyedrops;}}),
|
||||
LocationAccess(RC_DMT_TRADE_CLAIM_CHECK, {[]{return IsAdult && ClaimCheck;}}),
|
||||
LocationAccess(RC_DMT_GS_FALLING_ROCKS_PATH, {[]{return IsAdult && AtNight && (CanUse(RG_MEGATON_HAMMER) || LogicDMTGSUpper) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_DMT_GS_FALLING_ROCKS_PATH, {[]{return IsAdult && AtNight && (CanUse(RG_MEGATON_HAMMER) || randoCtx->GetTrickOption(RT_DMT_UPPER_GS)) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_DMT_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
@@ -85,14 +86,14 @@ void AreaTable_Init_DeathMountain() {
|
||||
EventAccess(&GoronCityChildFire, {[]{return GoronCityChildFire || (IsChild && CanUse(RG_DINS_FIRE));}}),
|
||||
EventAccess(&GCWoodsWarpOpen, {[]{return GCWoodsWarpOpen || (CanBlastOrSmash || CanUse(RG_DINS_FIRE) || CanUse(RG_FAIRY_BOW) || GoronBracelet || GoronCityChildFire);}}),
|
||||
EventAccess(&GCDaruniasDoorOpenChild, {[]{return GCDaruniasDoorOpenChild || (IsChild && CanPlay(ZeldasLullaby));}}),
|
||||
EventAccess(&StopGCRollingGoronAsAdult, {[]{return StopGCRollingGoronAsAdult || (IsAdult && (GoronBracelet || HasExplosives || Bow || (LogicGoronCityLinkGoronDins && CanUse(RG_DINS_FIRE))));}}),
|
||||
EventAccess(&StopGCRollingGoronAsAdult, {[]{return StopGCRollingGoronAsAdult || (IsAdult && (GoronBracelet || HasExplosives || Bow || (randoCtx->GetTrickOption(RT_GC_LINK_GORON_DINS) && CanUse(RG_DINS_FIRE))));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GC_MAZE_LEFT_CHEST, {[]{return CanUse(RG_MEGATON_HAMMER) || CanUse(RG_SILVER_GAUNTLETS) || (LogicGoronCityLeftMost && HasExplosives && CanUse(RG_HOVER_BOOTS));}}),
|
||||
LocationAccess(RC_GC_MAZE_LEFT_CHEST, {[]{return CanUse(RG_MEGATON_HAMMER) || CanUse(RG_SILVER_GAUNTLETS) || (randoCtx->GetTrickOption(RT_GC_LEFTMOST) && HasExplosives && CanUse(RG_HOVER_BOOTS));}}),
|
||||
LocationAccess(RC_GC_MAZE_CENTER_CHEST, {[]{return CanBlastOrSmash || CanUse(RG_SILVER_GAUNTLETS);}}),
|
||||
LocationAccess(RC_GC_MAZE_RIGHT_CHEST, {[]{return CanBlastOrSmash || CanUse(RG_SILVER_GAUNTLETS);}}),
|
||||
LocationAccess(RC_GC_POT_FREESTANDING_POH, {[]{return IsChild && GoronCityChildFire && (Bombs || (GoronBracelet && LogicGoronCityPotWithStrength) || (HasBombchus && LogicGoronCityPot));}}),
|
||||
LocationAccess(RC_GC_ROLLING_GORON_AS_CHILD, {[]{return IsChild && (HasExplosives || (GoronBracelet && LogicChildRollingWithStrength));}}),
|
||||
LocationAccess(RC_GC_POT_FREESTANDING_POH, {[]{return IsChild && GoronCityChildFire && (Bombs || (GoronBracelet && randoCtx->GetTrickOption(RT_GC_POT_STRENGTH)) || (HasBombchus && randoCtx->GetTrickOption(RT_GC_POT)));}}),
|
||||
LocationAccess(RC_GC_ROLLING_GORON_AS_CHILD, {[]{return IsChild && (HasExplosives || (GoronBracelet && randoCtx->GetTrickOption(RT_GC_ROLLING_STRENGTH)));}}),
|
||||
LocationAccess(RC_GC_ROLLING_GORON_AS_ADULT, {[]{return StopGCRollingGoronAsAdult;}}),
|
||||
LocationAccess(RC_GC_GS_BOULDER_MAZE, {[]{return IsChild && CanBlastOrSmash;}}),
|
||||
LocationAccess(RC_GC_GS_CENTER_PLATFORM, {[]{return CanAdultAttack;}}),
|
||||
@@ -105,7 +106,7 @@ void AreaTable_Init_DeathMountain() {
|
||||
Entrance(RR_GC_WOODS_WARP, {[]{return GCWoodsWarpOpen;}}),
|
||||
Entrance(RR_GC_SHOP, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || (IsChild && (CanBlastOrSmash || GoronBracelet || GoronCityChildFire || CanUse(RG_FAIRY_BOW)));}}),
|
||||
Entrance(RR_GC_DARUNIAS_CHAMBER, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || GCDaruniasDoorOpenChild;}}),
|
||||
Entrance(RR_GC_GROTTO_PLATFORM, {[]{return IsAdult && ((CanPlay(SongOfTime) && ((EffectiveHealth > 2) || CanUse(RG_GORON_TUNIC) || CanUse(RG_LONGSHOT) || CanUse(RG_NAYRUS_LOVE))) || (EffectiveHealth > 1 && CanUse(RG_GORON_TUNIC) && CanUse(RG_HOOKSHOT)) || (CanUse(RG_NAYRUS_LOVE) && CanUse(RG_HOOKSHOT)) || (EffectiveHealth > 2 && CanUse(RG_HOOKSHOT) && LogicGoronCityGrotto));}}),
|
||||
Entrance(RR_GC_GROTTO_PLATFORM, {[]{return IsAdult && ((CanPlay(SongOfTime) && ((EffectiveHealth > 2) || CanUse(RG_GORON_TUNIC) || CanUse(RG_LONGSHOT) || CanUse(RG_NAYRUS_LOVE))) || (EffectiveHealth > 1 && CanUse(RG_GORON_TUNIC) && CanUse(RG_HOOKSHOT)) || (CanUse(RG_NAYRUS_LOVE) && CanUse(RG_HOOKSHOT)) || (EffectiveHealth > 2 && CanUse(RG_HOOKSHOT) && randoCtx->GetTrickOption(RT_GC_GROTTO)));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_GC_WOODS_WARP] = Area("GC Woods Warp", "Goron City", RHT_GORON_CITY, NO_DAY_NIGHT_CYCLE, {
|
||||
@@ -179,7 +180,7 @@ void AreaTable_Init_DeathMountain() {
|
||||
//Exits
|
||||
Entrance(RR_DMC_UPPER_NEARBY, {[]{return true;}}),
|
||||
Entrance(RR_DMC_LADDER_AREA_NEARBY, {[]{return FireTimer >= 16 || Hearts >= 3;}}),
|
||||
Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && CanUse(RG_DISTANT_SCARECROW) && ((EffectiveHealth > 2) || (Fairy && ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) || CanUse(RG_NAYRUS_LOVE));}}),
|
||||
Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && CanUse(RG_DISTANT_SCARECROW) && ((EffectiveHealth > 2) || (Fairy && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)) || CanUse(RG_NAYRUS_LOVE));}}),
|
||||
Entrance(RR_DMC_LOWER_NEARBY, {[]{return false;}}),
|
||||
});
|
||||
|
||||
@@ -189,7 +190,7 @@ void AreaTable_Init_DeathMountain() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DMC_UPPER_NEARBY, {[]{return Hearts >= 3;}}),
|
||||
Entrance(RR_DMC_LOWER_NEARBY, {[]{return Hearts >= 3 && (CanUse(RG_HOVER_BOOTS) || (LogicCraterBoulderJS && IsAdult && CanUse(RG_MEGATON_HAMMER)) || (LogicCraterBoulderSkip && IsAdult));}}),
|
||||
Entrance(RR_DMC_LOWER_NEARBY, {[]{return Hearts >= 3 && (CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_DMC_BOULDER_JS) && IsAdult && CanUse(RG_MEGATON_HAMMER)) || (randoCtx->GetTrickOption(RT_DMC_BOULDER_SKIP) && IsAdult));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_DMC_LOWER_NEARBY] = Area("DMC Lower Nearby", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
@@ -205,12 +206,12 @@ void AreaTable_Init_DeathMountain() {
|
||||
Entrance(RR_DMC_LOWER_NEARBY, {[]{return true;}}),
|
||||
Entrance(RR_DMC_LADDER_AREA_NEARBY, {[]{return FireTimer >= 8 || Hearts >= 3;}}),
|
||||
Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT)) && (FireTimer >= 8 || Hearts >= 3);}}),
|
||||
Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT) || (IsAdult && CanShield && LogicCraterBoleroJump)) && FireTimer >= 24;}}),
|
||||
Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT) || (IsAdult && CanShield && randoCtx->GetTrickOption(RT_DMC_BOLERO_JUMP))) && FireTimer >= 24;}}),
|
||||
});
|
||||
|
||||
areaTable[RR_DMC_CENTRAL_NEARBY] = Area("DMC Central Nearby", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_DMC_VOLCANO_FREESTANDING_POH, {[]{return IsAdult && Hearts >= 3 && (CanPlantBean(RR_DMC_CENTRAL_LOCAL) || (LogicCraterBeanPoHWithHovers && HoverBoots));}}),
|
||||
LocationAccess(RC_DMC_VOLCANO_FREESTANDING_POH, {[]{return IsAdult && Hearts >= 3 && (CanPlantBean(RR_DMC_CENTRAL_LOCAL) || (randoCtx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && HoverBoots));}}),
|
||||
LocationAccess(RC_SHEIK_IN_CRATER, {[]{return IsAdult && (FireTimer >= 8 || Hearts >= 3);}}),
|
||||
}, {
|
||||
//Exits
|
||||
@@ -228,7 +229,7 @@ void AreaTable_Init_DeathMountain() {
|
||||
Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return true;}}),
|
||||
Entrance(RR_DMC_LOWER_NEARBY, {[]{return (IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL)) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT);}}),
|
||||
Entrance(RR_DMC_UPPER_NEARBY, {[]{return IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL);}}),
|
||||
Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return (IsChild && Hearts >= 3 && ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) || (IsAdult && FireTimer >= 24);}}),
|
||||
Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return (IsChild && Hearts >= 3 && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)) || (IsAdult && FireTimer >= 24);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "DMC Great Fairy Fountain", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_DekuTree() {
|
||||
/*--------------------------
|
||||
@@ -12,15 +12,15 @@ void AreaTable_Init_DekuTree() {
|
||||
---------------------------*/
|
||||
areaTable[RR_DEKU_TREE_ENTRYWAY] = Area("Deku Tree Entryway", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_DEKU_TREE_LOBBY, {[]{return Dungeon::DekuTree.IsVanilla();}}),
|
||||
Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return Dungeon::DekuTree.IsMQ();}}),
|
||||
Entrance(RR_DEKU_TREE_LOBBY, {[]{return randoCtx->GetDungeon(DEKU_TREE)->IsVanilla();}}),
|
||||
Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return randoCtx->GetDungeon(DEKU_TREE)->IsMQ();}}),
|
||||
Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::DekuTree.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(DEKU_TREE)->IsVanilla()) {
|
||||
areaTable[RR_DEKU_TREE_LOBBY] = Area("Deku Tree Lobby", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_BOOMERANG));}}),
|
||||
@@ -77,12 +77,12 @@ void AreaTable_Init_DekuTree() {
|
||||
//Locations
|
||||
LocationAccess(RC_DEKU_TREE_BASEMENT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_DEKU_TREE_GS_BASEMENT_GATE, {[]{return CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE);}}),
|
||||
LocationAccess(RC_DEKU_TREE_GS_BASEMENT_VINES, {[]{return CanUseProjectile || CanUse(RG_DINS_FIRE) || (LogicDekuBasementGS && CanJumpslash);}}),
|
||||
LocationAccess(RC_DEKU_TREE_GS_BASEMENT_VINES, {[]{return CanUseProjectile || CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && CanJumpslash);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DEKU_TREE_LOBBY, {[]{return true;}}),
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, {[]{return Here(RR_DEKU_TREE_BASEMENT_LOWER, []{return HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW);});}}),
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_UPPER, {[]{return IsAdult || LogicDekuB1Skip || HasAccessTo(RR_DEKU_TREE_BASEMENT_UPPER);}}),
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_UPPER, {[]{return IsAdult || randoCtx->GetTrickOption(RT_DEKU_B1_SKIP) || HasAccessTo(RR_DEKU_TREE_BASEMENT_UPPER);}}),
|
||||
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return false;}}),
|
||||
});
|
||||
|
||||
@@ -137,7 +137,7 @@ void AreaTable_Init_DekuTree() {
|
||||
//Exits
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_LOWER, {[]{return true;}}),
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, {[]{return IsChild;}}),
|
||||
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return Here(RR_DEKU_TREE_BASEMENT_UPPER, []{return HasFireSourceWithTorch || (LogicDekuB1WebsWithBow && IsAdult && CanUse(RG_FAIRY_BOW));});}}),
|
||||
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return Here(RR_DEKU_TREE_BASEMENT_UPPER, []{return HasFireSourceWithTorch || (randoCtx->GetTrickOption(RT_DEKU_B1_BOW_WEBS) && IsAdult && CanUse(RG_FAIRY_BOW));});}}),
|
||||
});
|
||||
|
||||
areaTable[RR_DEKU_TREE_OUTSIDE_BOSS_ROOM] = Area("Deku Tree Outside Boss Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
@@ -150,7 +150,7 @@ void AreaTable_Init_DekuTree() {
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::DekuTree.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(DEKU_TREE)->IsMQ()) {
|
||||
areaTable[RR_DEKU_TREE_MQ_LOBBY] = Area("Deku Tree MQ Lobby", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_BOOMERANG));}}),
|
||||
@@ -169,7 +169,7 @@ void AreaTable_Init_DekuTree() {
|
||||
Here(RR_DEKU_TREE_MQ_LOBBY, []{return HasFireSourceWithTorch || (IsAdult && CanUse(RG_FAIRY_BOW));});}}),
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, {[]{return Here(RR_DEKU_TREE_MQ_LOBBY, []{return (IsChild && CanUse(RG_FAIRY_SLINGSHOT)) || (IsAdult && CanUse(RG_FAIRY_BOW));}) &&
|
||||
Here(RR_DEKU_TREE_MQ_LOBBY, []{return HasFireSourceWithTorch;});}}),
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return LogicDekuB1Skip || Here(RR_DEKU_TREE_MQ_LOBBY, []{return IsAdult;});}}),
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return randoCtx->GetTrickOption(RT_DEKU_B1_SKIP) || Here(RR_DEKU_TREE_MQ_LOBBY, []{return IsAdult;});}}),
|
||||
});
|
||||
|
||||
areaTable[RR_DEKU_TREE_MQ_COMPASS_ROOM] = Area("Deku Tree MQ Compass Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -178,7 +178,7 @@ void AreaTable_Init_DekuTree() {
|
||||
LocationAccess(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, {[]{return HookshotOrBoomerang &&
|
||||
Here(RR_DEKU_TREE_MQ_COMPASS_ROOM, []{return HasBombchus ||
|
||||
(Bombs && (CanPlay(SongOfTime) || IsAdult)) ||
|
||||
(IsAdult && CanUse(RG_MEGATON_HAMMER) && (CanPlay(SongOfTime) || LogicDekuMQCompassGS));});}}),
|
||||
(IsAdult && CanUse(RG_MEGATON_HAMMER) && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS)));});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return true;}}),
|
||||
@@ -189,7 +189,7 @@ void AreaTable_Init_DekuTree() {
|
||||
LocationAccess(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return LogicDekuMQLog || (IsChild && (DekuShield || HylianShield)) ||
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return randoCtx->GetTrickOption(RT_DEKU_MQ_LOG) || (IsChild && (DekuShield || HylianShield)) ||
|
||||
(IsAdult && (CanUse(RG_LONGSHOT) || (CanUse(RG_HOOKSHOT) && CanUse(RG_IRON_BOOTS))));}}),
|
||||
Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return true;}}),
|
||||
});
|
||||
@@ -244,8 +244,8 @@ void AreaTable_Init_DekuTree() {
|
||||
Area("Deku Tree Boss Entryway", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {},
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, { [] { return Dungeon::DekuTree.IsVanilla(); } }),
|
||||
Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, { [] { return Dungeon::DekuTree.IsMQ(); } }),
|
||||
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, { [] { return randoCtx->GetDungeon(DEKU_TREE)->IsVanilla(); } }),
|
||||
Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, { [] { return randoCtx->GetDungeon(DEKU_TREE)->IsMQ(); } }),
|
||||
Entrance(RR_DEKU_TREE_BOSS_ROOM, { [] { return true; } }),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_DodongosCavern() {
|
||||
/*--------------------------
|
||||
@@ -12,15 +12,15 @@ void AreaTable_Init_DodongosCavern() {
|
||||
---------------------------*/
|
||||
areaTable[RR_DODONGOS_CAVERN_ENTRYWAY] = Area("Dodongos Cavern Entryway", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_BEGINNING, {[]{return Dungeon::DodongosCavern.IsVanilla();}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_BEGINNING, {[]{return Dungeon::DodongosCavern.IsMQ();}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_BEGINNING, {[]{return randoCtx->GetDungeon(DODONGOS_CAVERN)->IsVanilla();}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_BEGINNING, {[]{return randoCtx->GetDungeon(DODONGOS_CAVERN)->IsMQ();}}),
|
||||
Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::DodongosCavern.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(DODONGOS_CAVERN)->IsVanilla()) {
|
||||
areaTable[RR_DODONGOS_CAVERN_BEGINNING] = Area("Dodongos Cavern Beginning", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, {[]{return true;}}),
|
||||
@@ -54,7 +54,7 @@ void AreaTable_Init_DodongosCavern() {
|
||||
|
||||
areaTable[RR_DODONGOS_CAVERN_SE_CORRIDOR] = Area("Dodongos Cavern SE Corridor", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_DODONGOS_CAVERN_GS_SCARECROW, {[]{return CanUse(RG_SCARECROW) || (IsAdult && CanUse(RG_LONGSHOT)) || (LogicDCScarecrowGS && (CanAdultAttack || CanChildAttack));}}),
|
||||
LocationAccess(RC_DODONGOS_CAVERN_GS_SCARECROW, {[]{return CanUse(RG_SCARECROW) || (IsAdult && CanUse(RG_LONGSHOT)) || (randoCtx->GetTrickOption(RT_DC_SCARECROW_GS) && (CanAdultAttack || CanChildAttack));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
|
||||
@@ -102,14 +102,14 @@ void AreaTable_Init_DodongosCavern() {
|
||||
areaTable[RR_DODONGOS_CAVERN_STAIRS_LOWER] = Area("Dodongos Cavern Stairs Lower", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_STAIRS_UPPER, {[]{return HasExplosives || GoronBracelet || CanUse(RG_DINS_FIRE) || (LogicDCStaircase && CanUse(RG_FAIRY_BOW));}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_STAIRS_UPPER, {[]{return HasExplosives || GoronBracelet || CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_DC_STAIRCASE) && CanUse(RG_FAIRY_BOW));}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_COMPASS_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_STAIRS_LOWER, []{return CanBlastOrSmash || GoronBracelet;});}}),
|
||||
});
|
||||
|
||||
areaTable[RR_DODONGOS_CAVERN_STAIRS_UPPER] = Area("Dodongos Cavern Stairs Upper", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, {[]{return Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return HookshotOrBoomerang;}) || CanUse(RG_LONGSHOT);}}),
|
||||
LocationAccess(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, {[]{return IsAdult || CanChildAttack || (HasAccessTo(RR_DODONGOS_CAVERN_STAIRS_LOWER) && CanUse(RG_LONGSHOT) && LogicDCVinesGS);}}),
|
||||
LocationAccess(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, {[]{return IsAdult || CanChildAttack || (HasAccessTo(RR_DODONGOS_CAVERN_STAIRS_LOWER) && CanUse(RG_LONGSHOT) && randoCtx->GetTrickOption(RT_DC_VINES_GS));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, {[]{return true;}}),
|
||||
@@ -135,9 +135,9 @@ void AreaTable_Init_DodongosCavern() {
|
||||
LocationAccess(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || (LogicDCScrubRoom && GoronBracelet);});}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || (randoCtx->GetTrickOption(RT_DC_SCRUB_ROOM) && GoronBracelet);});}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || GoronBracelet;});}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return (IsAdult && LogicDCJump) || CanUse(RG_HOVER_BOOTS) || (IsAdult && CanUse(RG_LONGSHOT));}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return (IsAdult && randoCtx->GetTrickOption(RT_DC_JUMP)) || CanUse(RG_HOVER_BOOTS) || (IsAdult && CanUse(RG_LONGSHOT));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_DODONGOS_CAVERN_2F_SIDE_ROOM] = Area("Dodongos Cavern 2F Side Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -152,7 +152,7 @@ void AreaTable_Init_DodongosCavern() {
|
||||
areaTable[RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM] = Area("Dodongos Cavern First Slingshot Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || LogicDCSlingshotSkip;}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || randoCtx->GetTrickOption(RT_DC_SLINGSHOT_SKIP);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_DODONGOS_CAVERN_UPPER_LIZALFOS] = Area("Dodongos Cavern Upper Lizalfos", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
@@ -167,7 +167,7 @@ void AreaTable_Init_DodongosCavern() {
|
||||
areaTable[RR_DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM] = Area("Dodongos Cavern Second Slingshot Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return true;}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || LogicDCSlingshotSkip;}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || randoCtx->GetTrickOption(RT_DC_SLINGSHOT_SKIP);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER] = Area("Dodongos Cavern Bomb Room Upper", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -211,7 +211,7 @@ void AreaTable_Init_DodongosCavern() {
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::DodongosCavern.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(DODONGOS_CAVERN)->IsMQ()) {
|
||||
areaTable[RR_DODONGOS_CAVERN_MQ_BEGINNING] = Area("Dodongos Cavern MQ Beginning", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, {[]{return true;}}),
|
||||
@@ -227,7 +227,7 @@ void AreaTable_Init_DodongosCavern() {
|
||||
LocationAccess(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, {[]{return CanAdultAttack || CanChildAttack || Nuts;}}),
|
||||
LocationAccess(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, {[]{return (IsChild && CanUse(RG_STICKS)) || HasFireSource;}}),
|
||||
LocationAccess(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, {[]{return CanBlastOrSmash || (IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) || (IsAdult && (LogicDCJump || HoverBoots || Hookshot));}}),
|
||||
LocationAccess(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, {[]{return CanBlastOrSmash || (IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) || (IsAdult && (randoCtx->GetTrickOption(RT_DC_JUMP) || HoverBoots || Hookshot));}}),
|
||||
LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, {[]{return CanPlay(SongOfTime) && (CanChildAttack || CanAdultAttack);}}),
|
||||
LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, {[]{return (IsChild && CanUse(RG_STICKS)) || HasFireSource;}}),
|
||||
LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, {[]{return CanBlastOrSmash;}}),
|
||||
@@ -238,9 +238,9 @@ void AreaTable_Init_DodongosCavern() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return CanBlastOrSmash || (((IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE)) && CanTakeDamage);});}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return IsAdult || (Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return IsAdult;}) && HasExplosives) || (LogicDCMQChildBombs && CanJumpslash && CanTakeDamage);}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return IsAdult || (Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return IsAdult;}) && HasExplosives) || (randoCtx->GetTrickOption(RT_DC_MQ_CHILD_BOMBS) && CanJumpslash && CanTakeDamage);}}),
|
||||
//Trick: IsAdult || HasExplosives || (LogicDCMQChildBombs && (KokiriSword || Sticks) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, {[]{return HasExplosives || (GoronBracelet && ((IsAdult && LogicDCMQEyesAdult) || (IsChild && LogicDCMQEyesChild)) && ((IsChild && (CanUse(RG_STICKS))) || CanUse(RG_DINS_FIRE) || (IsAdult && (LogicDCJump || Hammer || HoverBoots || Hookshot))));}}),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, {[]{return HasExplosives || (GoronBracelet && ((IsAdult && randoCtx->GetTrickOption(RT_DC_MQ_ADULT_EYES)) || (IsChild && randoCtx->GetTrickOption(RT_DC_MQ_CHILD_EYES))) && ((IsChild && (CanUse(RG_STICKS))) || CanUse(RG_DINS_FIRE) || (IsAdult && (randoCtx->GetTrickOption(RT_DC_JUMP) || Hammer || HoverBoots || Hookshot))));}}),
|
||||
//Trick: HasExplosives || (LogicDCMQEyes && GoronBracelet && (IsAdult || LogicDCMQChildBack) && ((IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) || (IsAdult && (LogicDCJump || Hammer || HoverBoots || Hookshot))))
|
||||
});
|
||||
|
||||
@@ -283,8 +283,8 @@ void AreaTable_Init_DodongosCavern() {
|
||||
Area("Dodongos Cavern Boss Entryway", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {},
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, { [] { return Dungeon::DodongosCavern.IsVanilla(); } }),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, { [] { return Dungeon::DodongosCavern.IsMQ(); } }),
|
||||
Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, { [] { return randoCtx->GetDungeon(DODONGOS_CAVERN)->IsVanilla(); } }),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, { [] { return randoCtx->GetDungeon(DODONGOS_CAVERN)->IsMQ(); } }),
|
||||
Entrance(RR_DODONGOS_CAVERN_BOSS_ROOM, { [] { return true; } }),
|
||||
});
|
||||
|
||||
@@ -296,7 +296,7 @@ void AreaTable_Init_DodongosCavern() {
|
||||
{ [] {
|
||||
return DodongosCavernClear || (HasBossSoul(RG_KING_DODONGO_SOUL) &&
|
||||
(Here(RR_DODONGOS_CAVERN_BOSS_ROOM,
|
||||
[] { return HasExplosives || (CanUse(RG_MEGATON_HAMMER) && LogicDCHammerFloor); }) &&
|
||||
[] { return HasExplosives || (CanUse(RG_MEGATON_HAMMER) && randoCtx->GetTrickOption(RT_DC_HAMMER_FLOOR)); }) &&
|
||||
(Bombs || GoronBracelet) && CanJumpslash)); /*todo add chu kill to tricks*/
|
||||
}}),
|
||||
},
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_FireTemple() {
|
||||
/*--------------------------
|
||||
@@ -12,15 +12,15 @@ void AreaTable_Init_FireTemple() {
|
||||
---------------------------*/
|
||||
areaTable[RR_FIRE_TEMPLE_ENTRYWAY] = Area("Fire Temple Entryway", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return Dungeon::FireTemple.IsVanilla();}}),
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_LOWER, {[]{return Dungeon::FireTemple.IsMQ();}}),
|
||||
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return randoCtx->GetDungeon(FIRE_TEMPLE)->IsVanilla();}}),
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_LOWER, {[]{return randoCtx->GetDungeon(FIRE_TEMPLE)->IsMQ();}}),
|
||||
Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::FireTemple.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(FIRE_TEMPLE)->IsVanilla()) {
|
||||
areaTable[RR_FIRE_TEMPLE_FIRST_ROOM] = Area("Fire Temple First Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
}, {
|
||||
//Exits
|
||||
@@ -40,7 +40,7 @@ void AreaTable_Init_FireTemple() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && LogicFireBossDoorJump) || CanUse(RG_HOVER_BOOTS) || Here(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(RG_MEGATON_HAMMER);}));}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && randoCtx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP)) || CanUse(RG_HOVER_BOOTS) || Here(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(RG_MEGATON_HAMMER);}));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_LOOP_ENEMIES] = Area("Fire Temple Loop Enemies", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
@@ -96,7 +96,7 @@ void AreaTable_Init_FireTemple() {
|
||||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 2);}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON, {[]{return true;}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, {[]{return IsAdult && (CanPlay(SongOfTime) || LogicFireSongOfTime);}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, {[]{return IsAdult && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_FIRE_SOT));}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON, {[]{return IsAdult && HasExplosives;}}),
|
||||
Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 3);}}),
|
||||
});
|
||||
@@ -138,7 +138,7 @@ void AreaTable_Init_FireTemple() {
|
||||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 4);}}),
|
||||
Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, {[]{return Here(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;});}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return IsAdult && (GoronBracelet || LogicFireStrength) && (HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT));}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return IsAdult && (GoronBracelet || randoCtx->GetTrickOption(RT_FIRE_STRENGTH)) && (HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_SHORTCUT_CLIMB] = Area("Fire Temple Shortcut Climb", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
@@ -199,7 +199,7 @@ void AreaTable_Init_FireTemple() {
|
||||
Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, {[]{return HasExplosives;}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return true;}}),
|
||||
Entrance(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, {[]{return true;}}),
|
||||
Entrance(RR_FIRE_TEMPLE_SCARECROW_ROOM, {[]{return CanUse(RG_SCARECROW) || (LogicFireScarecrow && IsAdult && CanUse(RG_LONGSHOT));}}),
|
||||
Entrance(RR_FIRE_TEMPLE_SCARECROW_ROOM, {[]{return CanUse(RG_SCARECROW) || (randoCtx->GetTrickOption(RT_FIRE_SCARECROW) && IsAdult && CanUse(RG_LONGSHOT));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_SCARECROW_ROOM] = Area("Fire Temple Scarecrow Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -233,7 +233,7 @@ void AreaTable_Init_FireTemple() {
|
||||
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return CanUse(RG_HOVER_BOOTS);}}),
|
||||
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM, {[]{return true;}}),
|
||||
Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER, {[]{return SmallKeys(RR_FIRE_TEMPLE, 8);}}),
|
||||
Entrance(RR_FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return LogicFireFlameMaze || false;}}),
|
||||
Entrance(RR_FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return randoCtx->GetTrickOption(RT_FIRE_FLAME_MAZE) || false;}}),
|
||||
});
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_FIRE_MAZE_UPPER] = Area("Fire Temple Fire Maze Upper", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
@@ -253,7 +253,7 @@ void AreaTable_Init_FireTemple() {
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER] = Area("Fire Temple West Central Lower", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, {[]{return Here(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (CanPlay(SongOfTime) || LogicRustedSwitches) && CanUse(RG_MEGATON_HAMMER);});}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, {[]{return Here(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && CanUse(RG_MEGATON_HAMMER);});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 8);}}),
|
||||
@@ -314,16 +314,16 @@ void AreaTable_Init_FireTemple() {
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::FireTemple.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(FIRE_TEMPLE)->IsMQ()) {
|
||||
areaTable[RR_FIRE_TEMPLE_MQ_LOWER] = Area("Fire Temple MQ Lower", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, {[]{return CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || Bombs || CanUse(RG_DINS_FIRE);}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, {[]{return IsAdult && (LogicFewerTunicRequirements || CanUse(RG_GORON_TUNIC)) && (((CanUse(RG_HOVER_BOOTS) || (LogicFireMQNearBoss && CanUse(RG_FAIRY_BOW))) && HasFireSource) || (CanUse(RG_HOOKSHOT) && CanUse(RG_FIRE_ARROWS) || (CanUse(RG_DINS_FIRE) && ((DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_QUADRUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OCTUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_SEXDECUPLE)) || CanUse(RG_GORON_TUNIC) || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)))));}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, {[]{return IsAdult && (randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_GORON_TUNIC)) && (((CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && CanUse(RG_FAIRY_BOW))) && HasFireSource) || (CanUse(RG_HOOKSHOT) && CanUse(RG_FIRE_ARROWS) || (CanUse(RG_DINS_FIRE) && ((randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_QUADRUPLE) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OCTUPLE) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_SEXDECUPLE)) || CanUse(RG_GORON_TUNIC) || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)))));}}),
|
||||
//Trick: IsAdult && (LogicFewerTunicRequirements || CanUse(RG_GORON_TUNIC)) && (((CanUse(RG_HOVER_BOOTS) || (LogicFireMQNearBoss && CanUse(RG_FAIRY_BOW))) && HasFireSource) || (CanUse(RG_HOOKSHOT) && CanUse(RG_FIRE_ARROWS) || (CanUse(RG_DINS_FIRE) && ((DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_QUADRUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OCTUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_SEXDECUPLE)) || CanUse(RG_GORON_TUNIC) || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)))))
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && CanUse(RG_MEGATON_HAMMER) && BossKeyFireTemple && ((HasFireSource && (LogicFireBossDoorJump || HoverBoots)) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER));}}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && CanUse(RG_MEGATON_HAMMER) && BossKeyFireTemple && ((HasFireSource && (randoCtx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || HoverBoots)) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER));}}),
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR, {[]{return SmallKeys(RR_FIRE_TEMPLE, 5) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD));}}),
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, {[]{return IsAdult && FireTimer >= 24 && CanUse(RG_MEGATON_HAMMER);}}),
|
||||
});
|
||||
@@ -339,29 +339,29 @@ void AreaTable_Init_FireTemple() {
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM] = Area("Fire Temple MQ Big Lava Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return FairyPot || (HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireSongOfTime));}}),
|
||||
EventAccess(&FairyPot, {[]{return FairyPot || (HasFireSource && (Bow || randoCtx->GetTrickOption(RT_FIRE_MQ_BK_CHEST)) && IsAdult && (CanUse(RG_HOOKSHOT) || randoCtx->GetTrickOption(RT_FIRE_SOT)));}}),
|
||||
//Trick: HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireSongOfTime)
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && CanUse(RG_HOOKSHOT);}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return HasFireSource && (Bow || randoCtx->GetTrickOption(RT_FIRE_MQ_BK_CHEST)) && IsAdult && CanUse(RG_HOOKSHOT);}}),
|
||||
//Trick: HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && CanUse(RG_HOOKSHOT)
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return HasFireSource && HasExplosives && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireMQBlockedChest);}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return HasFireSource && HasExplosives && IsAdult && (CanUse(RG_HOOKSHOT) || randoCtx->GetTrickOption(RT_FIRE_MQ_BLOCKED_CHEST));}}),
|
||||
//Trick: HasFireSource && HasExplosives && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireMQBlockedChest)
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && SmallKeys(RR_FIRE_TEMPLE, 2) && (HasFireSource || (LogicFireMQClimb && HoverBoots));}}),
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && SmallKeys(RR_FIRE_TEMPLE, 2) && (HasFireSource || (randoCtx->GetTrickOption(RT_FIRE_MQ_CLIMB) && HoverBoots));}}),
|
||||
//Trick: IsAdult && CanUse(RG_GORON_TUNIC) && SmallKeys(RR_FIRE_TEMPLE, 2) && (HasFireSource || (LogicFireMQClimb && HoverBoots))
|
||||
});
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_MQ_LOWER_MAZE] = Area("Fire Temple MQ Lower Maze", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, {[]{return CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, {[]{return HasExplosives && (LogicFireMQMazeSideRoom || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER_MAZE));}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, {[]{return HasExplosives && (randoCtx->GetTrickOption(RT_FIRE_MQ_MAZE_SIDE_ROOM) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER_MAZE));}}),
|
||||
//Trick: HasExplosives && (LogicFireMQMazeSideRoom || FIRE_TEMPLE_MQ_UPPER_MAZE.Adult())
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return (IsAdult && ((HasExplosives && CanUse(RG_HOOKSHOT)) || (LogicFireMQMazeHovers && CanUse(RG_HOVER_BOOTS)))) || LogicFireMQMazeJump;}}),
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return (IsAdult && ((HasExplosives && CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_FIRE_MQ_MAZE_HOVERS) && CanUse(RG_HOVER_BOOTS)))) || randoCtx->GetTrickOption(RT_FIRE_MQ_MAZE_JUMP);}}),
|
||||
//Trick: (IsAdult && ((HasExplosives && CanUse(RG_HOOKSHOT)) || (LogicFireMQMazeHovers && CanUse(RG_HOVER_BOOTS)))) || LogicFireMQMazeJump
|
||||
});
|
||||
|
||||
@@ -381,14 +381,14 @@ void AreaTable_Init_FireTemple() {
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_MQ_UPPER] = Area("Fire Temple MQ Upper", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, {[]{return ((CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG)) && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze;}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, {[]{return ((CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG)) && CanUse(RG_HOOKSHOT)) || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}),
|
||||
//Trick: (IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, {[]{return ((IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze) && SmallKeys(RR_FIRE_TEMPLE, 4);}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, {[]{return ((IsAdult && CanUse(RG_HOOKSHOT)) || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE)) && SmallKeys(RR_FIRE_TEMPLE, 4);}}),
|
||||
//Trick: ((IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze) && SmallKeys(RR_FIRE_TEMPLE, 4)
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, {[]{return CanPlay(SongOfTime) || HoverBoots || LogicFireMQFlameMaze;}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, {[]{return CanPlay(SongOfTime) || HoverBoots || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}),
|
||||
//Trick: CanPlay(SongOfTime) || HoverBoots || LogicFireMQFlameMaze
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, {[]{return HasExplosives;}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, {[]{return (IsAdult && CanUse(RG_HOOKSHOT) && SmallKeys(RR_FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(RG_LONGSHOT));}}),
|
||||
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, {[]{return (IsAdult && CanUse(RG_HOOKSHOT) && SmallKeys(RR_FIRE_TEMPLE, 5)) || (randoCtx->GetTrickOption(RT_FIRE_MQ_ABOVE_MAZE_GS) && IsAdult && CanUse(RG_LONGSHOT));}}),
|
||||
//Trick: (IsAdult && CanUse(RG_HOOKSHOT) && SmallKeys(RR_FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(RG_LONGSHOT))
|
||||
}, {});
|
||||
}
|
||||
@@ -400,8 +400,8 @@ void AreaTable_Init_FireTemple() {
|
||||
Area("Fire Temple Boss Entryway", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, { [] { return Dungeon::FireTemple.IsVanilla() && false; } }),
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_LOWER, { [] { return Dungeon::FireTemple.IsMQ() && false; } }),
|
||||
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, { [] { return randoCtx->GetDungeon(FIRE_TEMPLE)->IsVanilla() && false; } }),
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_LOWER, { [] { return randoCtx->GetDungeon(FIRE_TEMPLE)->IsMQ() && false; } }),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ROOM, { [] { return true; } }),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_ForestTemple() {
|
||||
/*--------------------------
|
||||
@@ -12,19 +12,19 @@ void AreaTable_Init_ForestTemple() {
|
||||
---------------------------*/
|
||||
areaTable[RR_FOREST_TEMPLE_ENTRYWAY] = Area("Forest Temple Entryway", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_FIRST_ROOM, {[]{return Dungeon::ForestTemple.IsVanilla();}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, {[]{return Dungeon::ForestTemple.IsMQ();}}),
|
||||
Entrance(RR_FOREST_TEMPLE_FIRST_ROOM, {[]{return randoCtx->GetDungeon(FOREST_TEMPLE)->IsVanilla();}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, {[]{return randoCtx->GetDungeon(FOREST_TEMPLE)->IsMQ();}}),
|
||||
Entrance(RR_SACRED_FOREST_MEADOW, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::ForestTemple.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(FOREST_TEMPLE)->IsVanilla()) {
|
||||
areaTable[RR_FOREST_TEMPLE_FIRST_ROOM] = Area("Forest Temple First Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_FOREST_TEMPLE_GS_FIRST_ROOM, {[]{return (IsAdult && Bombs) || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG) || CanUse(RG_FAIRY_SLINGSHOT) || HasBombchus || CanUse(RG_DINS_FIRE) || (LogicForestFirstGS && (CanJumpslash || (IsChild && Bombs)));}}),
|
||||
LocationAccess(RC_FOREST_TEMPLE_GS_FIRST_ROOM, {[]{return (IsAdult && Bombs) || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG) || CanUse(RG_FAIRY_SLINGSHOT) || HasBombchus || CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_FOREST_FIRST_GS) && (CanJumpslash || (IsChild && Bombs)));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
@@ -106,12 +106,12 @@ void AreaTable_Init_ForestTemple() {
|
||||
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_MEGATON_HAMMER) || HasExplosives || CanUse(RG_DINS_FIRE));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, {[]{return CanUse(RG_HOOKSHOT) || HasAccessTo(RR_FOREST_TEMPLE_FALLING_ROOM) || (HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) && IsAdult && LogicForestOutdoorsLedge && HoverBoots);}}),
|
||||
LocationAccess(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, {[]{return CanUse(RG_HOOKSHOT) || (LogicForestOutdoorEastGS && CanUse(RG_BOOMERANG)) || Here(RR_FOREST_TEMPLE_FALLING_ROOM, []{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_DINS_FIRE) || HasExplosives;});}}),
|
||||
LocationAccess(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, {[]{return CanUse(RG_HOOKSHOT) || HasAccessTo(RR_FOREST_TEMPLE_FALLING_ROOM) || (HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) && IsAdult && randoCtx->GetTrickOption(RT_FOREST_OUTDOORS_LEDGE) && HoverBoots);}}),
|
||||
LocationAccess(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, {[]{return CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_FOREST_OUTDOORS_EAST_GS) && CanUse(RG_BOOMERANG)) || Here(RR_FOREST_TEMPLE_FALLING_ROOM, []{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_DINS_FIRE) || HasExplosives;});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return true;}}),
|
||||
Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER, {[]{return CanUse(RG_LONGSHOT) || (LogicForestVines && CanUse(RG_HOOKSHOT));}}),
|
||||
Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER, {[]{return CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_FOREST_VINES) && CanUse(RG_HOOKSHOT));}}),
|
||||
Entrance(RR_FOREST_TEMPLE_SEWER, {[]{return GoldScale || CanUse(RG_IRON_BOOTS) || HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}),
|
||||
Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, {[]{return false;}}),
|
||||
});
|
||||
@@ -124,7 +124,7 @@ void AreaTable_Init_ForestTemple() {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return true;}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MAP_ROOM, {[]{return true;}}),
|
||||
Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, {[]{return LogicForestDoorFrame && CanJumpslash && CanUse(RG_HOVER_BOOTS) && CanUse(RG_SCARECROW);}}),
|
||||
Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, {[]{return randoCtx->GetTrickOption(RT_FOREST_DOORFRAME) && CanJumpslash && CanUse(RG_HOVER_BOOTS) && CanUse(RG_SCARECROW);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_FOREST_TEMPLE_MAP_ROOM] = Area("Forest Temple Map Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -170,7 +170,7 @@ void AreaTable_Init_ForestTemple() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, {[]{return true;}}),
|
||||
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return CanUse(RG_HOVER_BOOTS) || (LogicForestOutsideBackdoor && CanJumpslash && GoronBracelet);}}),
|
||||
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && CanJumpslash && GoronBracelet);}}),
|
||||
Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return IsAdult && GoronBracelet && SmallKeys(RR_FOREST_TEMPLE, 2);}}),
|
||||
Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT)) && GoronBracelet && SmallKeys(RR_FOREST_TEMPLE, 2);}}),
|
||||
});
|
||||
@@ -279,7 +279,7 @@ void AreaTable_Init_ForestTemple() {
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::ForestTemple.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(FOREST_TEMPLE)->IsMQ()) {
|
||||
areaTable[RR_FOREST_TEMPLE_MQ_LOBBY] = Area("Forest Temple MQ Lobby", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, {[]{return CanJumpslash || Bombs || CanUse(RG_STICKS) || Nuts || HookshotOrBoomerang || CanUse(RG_DINS_FIRE) || KokiriSword || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOVER_BOOTS);}}),
|
||||
@@ -301,9 +301,9 @@ void AreaTable_Init_ForestTemple() {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT);}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT);}}), //This is as far as child can get
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE, {[]{return IsAdult && (GoronBracelet || (LogicForestMQBlockPuzzle && HasBombchus && IsAdult && CanUse(RG_HOOKSHOT)));}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE, {[]{return IsAdult && (GoronBracelet || (randoCtx->GetTrickOption(RT_FOREST_MQ_BLOCK_PUZZLE) && HasBombchus && IsAdult && CanUse(RG_HOOKSHOT)));}}),
|
||||
//Trick: IsAdult && (GoronBracelet || (LogicForestMQBlockPuzzle && HasBombchus && IsAdult && CanUse(RG_HOOKSHOT)))
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return (LogicForestMQHallwaySwitchJS && IsAdult && CanUse(RG_HOVER_BOOTS)) || (LogicForestMQHallwaySwitchBoomerang && CanUse(RG_BOOMERANG)) || (LogicForestMQHallwaySwitchHookshot && IsAdult && CanUse(RG_HOOKSHOT));}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return (randoCtx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && IsAdult && CanUse(RG_HOVER_BOOTS)) || (randoCtx->GetTrickOption(RT_FOREST_MQ_RANG_HALLWAY_SWITCH) && CanUse(RG_BOOMERANG)) || (randoCtx->GetTrickOption(RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH) && IsAdult && CanUse(RG_HOOKSHOT));}}),
|
||||
//Trick (Hookshot trick not added to either n64 or oot3d rando as of yet, to enable in SoH needs uncommenting in randomizer_tricks.cpp): (LogicForestMQHallwaySwitchJS && IsAdult && CanUse(RG_HOVER_BOOTS)) || (LogicForestMQHallwaySwitchHookshot && IsAdult && CanUse(RG_HOOKSHOT))
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, {[]{return ForestTempleJoAndBeth && ForestTempleAmyAndMeg;}}),
|
||||
});
|
||||
@@ -314,7 +314,7 @@ void AreaTable_Init_ForestTemple() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_BOW_REGION, {[]{return SmallKeys(RR_FOREST_TEMPLE, 4);}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return SmallKeys(RR_FOREST_TEMPLE, 3) || (LogicForestMQHallwaySwitchJS && ((IsAdult && CanUse(RG_HOOKSHOT)) || (LogicForestOutsideBackdoor && (IsAdult || (IsChild && CanUse(RG_STICKS))))));}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return SmallKeys(RR_FOREST_TEMPLE, 3) || (randoCtx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && ((IsAdult && CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && (IsAdult || (IsChild && CanUse(RG_STICKS))))));}}),
|
||||
//Trick (Doing the hallway switch jumpslash as child requires sticks and has been added above): SmallKeys(RR_FOREST_TEMPLE, 3) || (LogicForestMQHallwaySwitchJS && ((IsAdult && CanUse(RG_HOOKSHOT)) || LogicForestOutsideBackdoor))
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return SmallKeys(RR_FOREST_TEMPLE, 2);}}),
|
||||
});
|
||||
@@ -332,7 +332,7 @@ void AreaTable_Init_ForestTemple() {
|
||||
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, {[]{return CanAdultAttack || CanChildAttack;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return (IsAdult && (CanUse(RG_IRON_BOOTS) || CanUse(RG_LONGSHOT) || (LogicForestMQWellSwim && CanUse(RG_HOOKSHOT)))) || ProgressiveScale >= 2;}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return (IsAdult && (CanUse(RG_IRON_BOOTS) || CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_FOREST_MQ_WELL_SWIM) && CanUse(RG_HOOKSHOT)))) || ProgressiveScale >= 2;}}),
|
||||
//Trick: (IsAdult && (CanUse(RG_IRON_BOOTS) || CanUse(RG_LONGSHOT) || (LogicForestMQWellSwim && CanUse(RG_HOOKSHOT)))) || ProgressiveScale >= 2
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, {[]{return IsAdult && CanUse(RG_FIRE_ARROWS);}}),
|
||||
});
|
||||
@@ -344,7 +344,7 @@ void AreaTable_Init_ForestTemple() {
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_FOREST_TEMPLE_MQ_WELL_CHEST, {[]{return (IsAdult && CanUse(RG_FAIRY_BOW)) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}),
|
||||
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, {[]{return HookshotOrBoomerang || (IsAdult && CanUse(RG_FIRE_ARROWS) && (CanPlay(SongOfTime) || (CanUse(RG_HOVER_BOOTS) && LogicForestDoorFrame)));}}),
|
||||
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, {[]{return HookshotOrBoomerang || (IsAdult && CanUse(RG_FIRE_ARROWS) && (CanPlay(SongOfTime) || (CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_FOREST_DOORFRAME))));}}),
|
||||
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_WELL, {[]{return (IsAdult && ((CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT)) || CanUse(RG_FAIRY_BOW))) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}),
|
||||
}, {
|
||||
//Exits
|
||||
@@ -358,7 +358,7 @@ void AreaTable_Init_ForestTemple() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return true;}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return LogicForestOutdoorsLedge && IsAdult && CanUse(RG_HOVER_BOOTS);}}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return randoCtx->GetTrickOption(RT_FOREST_OUTDOORS_LEDGE) && IsAdult && CanUse(RG_HOVER_BOOTS);}}),
|
||||
//Trick: LogicForestOutdoorsLedge && IsAdult && CanUse(RG_HOVER_BOOTS)
|
||||
});
|
||||
|
||||
@@ -411,8 +411,8 @@ void AreaTable_Init_ForestTemple() {
|
||||
Area("Forest Temple Boss Entryway", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_REGION, { [] { return Dungeon::ForestTemple.IsVanilla() && false; } }),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, { [] { return Dungeon::ForestTemple.IsMQ() && false; } }),
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_REGION, { [] { return randoCtx->GetDungeon(FOREST_TEMPLE)->IsVanilla() && false; } }),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, { [] { return randoCtx->GetDungeon(FOREST_TEMPLE)->IsMQ() && false; } }),
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_ROOM, { [] { return true; } }),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../trial.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
#include "../../trial.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_GanonsCastle() {
|
||||
/*--------------------------
|
||||
@@ -13,15 +13,15 @@ void AreaTable_Init_GanonsCastle() {
|
||||
---------------------------*/
|
||||
areaTable[RR_GANONS_CASTLE_ENTRYWAY] = Area("Ganon's Castle Entryway", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_GANONS_CASTLE_LOBBY, {[]{return Dungeon::GanonsCastle.IsVanilla();}}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_LOBBY, {[]{return Dungeon::GanonsCastle.IsMQ();}}),
|
||||
Entrance(RR_GANONS_CASTLE_LOBBY, {[]{return randoCtx->GetDungeon(GANONS_CASTLE)->IsVanilla();}}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_LOBBY, {[]{return randoCtx->GetDungeon(GANONS_CASTLE)->IsMQ();}}),
|
||||
Entrance(RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::GanonsCastle.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(GANONS_CASTLE)->IsVanilla()) {
|
||||
areaTable[RR_GANONS_CASTLE_LOBBY] = Area("Ganon's Castle Lobby", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SHEIK_HINT_GC, {[]{return true;}}),
|
||||
@@ -34,13 +34,13 @@ void AreaTable_Init_GanonsCastle() {
|
||||
Entrance(RR_GANONS_CASTLE_SHADOW_TRIAL, {[]{return true;}}),
|
||||
Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL, {[]{return true;}}),
|
||||
Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL, {[]{return CanUse(RG_GOLDEN_GAUNTLETS);}}),
|
||||
Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || Trial::ForestTrial.IsSkipped()) &&
|
||||
(FireTrialClear || Trial::FireTrial.IsSkipped()) &&
|
||||
(WaterTrialClear || Trial::WaterTrial.IsSkipped()) &&
|
||||
(ShadowTrialClear || Trial::ShadowTrial.IsSkipped()) &&
|
||||
(SpiritTrialClear || Trial::SpiritTrial.IsSkipped()) &&
|
||||
(LightTrialClear || Trial::LightTrial.IsSkipped());}}),
|
||||
Entrance(RR_GANONS_CASTLE_DEKU_SCRUBS, {[]{return LogicLensCastle || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || randoCtx->GetTrial(Rando::FOREST_TRIAL)->IsSkipped()) &&
|
||||
(FireTrialClear || randoCtx->GetTrial(Rando::FIRE_TRIAL)->IsSkipped()) &&
|
||||
(WaterTrialClear || randoCtx->GetTrial(Rando::WATER_TRIAL)->IsSkipped()) &&
|
||||
(ShadowTrialClear || randoCtx->GetTrial(Rando::SHADOW_TRIAL)->IsSkipped()) &&
|
||||
(SpiritTrialClear || randoCtx->GetTrial(Rando::SPIRIT_TRIAL)->IsSkipped()) &&
|
||||
(LightTrialClear || randoCtx->GetTrial(Rando::LIGHT_TRIAL)->IsSkipped());}}),
|
||||
Entrance(RR_GANONS_CASTLE_DEKU_SCRUBS, {[]{return randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_GANONS_CASTLE_DEKU_SCRUBS] = Area("Ganon's Castle Deku Scrubs", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
@@ -80,7 +80,7 @@ void AreaTable_Init_GanonsCastle() {
|
||||
|
||||
areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL] = Area("Ganon's Castle Shadow Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ShadowTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && CanUse(RG_MEGATON_HAMMER) && ((FireArrows && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH))) || (CanUse(RG_LONGSHOT) && (CanUse(RG_HOVER_BOOTS) || (DinsFire && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH))))));}}),
|
||||
EventAccess(&ShadowTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && CanUse(RG_MEGATON_HAMMER) && ((FireArrows && (randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH))) || (CanUse(RG_LONGSHOT) && (CanUse(RG_HOVER_BOOTS) || (DinsFire && (randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH))))));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, {[]{return CanUse(RG_FIRE_ARROWS) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || CanPlay(SongOfTime) || IsChild;}}),
|
||||
@@ -89,17 +89,17 @@ void AreaTable_Init_GanonsCastle() {
|
||||
|
||||
areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL] = Area("Ganon's Castle Spirit Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&NutPot, {[]{return NutPot || (((LogicSpiritTrialHookshot && CanJumpslash) || CanUse(RG_HOOKSHOT)) && HasBombchus && CanUse(RG_FAIRY_BOW) && (CanUse(RG_MIRROR_SHIELD) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS))));}}),
|
||||
EventAccess(&SpiritTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_MIRROR_SHIELD) || SunlightArrows) && HasBombchus && ((LogicSpiritTrialHookshot && CanJumpslash) || CanUse(RG_HOOKSHOT));}}),
|
||||
EventAccess(&NutPot, {[]{return NutPot || (((randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && CanJumpslash) || CanUse(RG_HOOKSHOT)) && HasBombchus && CanUse(RG_FAIRY_BOW) && (CanUse(RG_MIRROR_SHIELD) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))));}}),
|
||||
EventAccess(&SpiritTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_MIRROR_SHIELD) || randoCtx->GetOption(RSK_SUNLIGHT_ARROWS)) && HasBombchus && ((randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && CanJumpslash) || CanUse(RG_HOOKSHOT));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, {[]{return (LogicSpiritTrialHookshot || CanUse(RG_HOOKSHOT)) && CanJumpslash;}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return (LogicSpiritTrialHookshot || CanUse(RG_HOOKSHOT)) && HasBombchus && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, {[]{return (randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || CanUse(RG_HOOKSHOT)) && CanJumpslash;}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || CanUse(RG_HOOKSHOT)) && HasBombchus && (randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
}, {});
|
||||
|
||||
areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL] = Area("Ganon's Castle Light Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&LightTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && CanUse(RG_HOOKSHOT) && SmallKeys(RR_GANONS_CASTLE, 2) && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
EventAccess(&LightTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && CanUse(RG_HOOKSHOT) && SmallKeys(RR_GANONS_CASTLE, 2) && (randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, {[]{return true;}}),
|
||||
@@ -108,7 +108,7 @@ void AreaTable_Init_GanonsCastle() {
|
||||
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, {[]{return LogicLensCastle || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(RR_GANONS_CASTLE, 1);}}),
|
||||
}, {});
|
||||
}
|
||||
@@ -123,7 +123,7 @@ void AreaTable_Init_GanonsCastle() {
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::GanonsCastle.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(GANONS_CASTLE)->IsMQ()) {
|
||||
areaTable[RR_GANONS_CASTLE_MQ_LOBBY] = Area("Ganon's Castle MQ Lobby", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SHEIK_HINT_MQ_GC, {[]{return true;}}),
|
||||
@@ -136,13 +136,13 @@ void AreaTable_Init_GanonsCastle() {
|
||||
Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL, {[]{return true;}}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL, {[]{return true;}}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL, {[]{return CanUse(RG_GOLDEN_GAUNTLETS);}}),
|
||||
Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || Trial::ForestTrial.IsSkipped()) &&
|
||||
(FireTrialClear || Trial::FireTrial.IsSkipped()) &&
|
||||
(WaterTrialClear || Trial::WaterTrial.IsSkipped()) &&
|
||||
(ShadowTrialClear || Trial::ShadowTrial.IsSkipped()) &&
|
||||
(SpiritTrialClear || Trial::SpiritTrial.IsSkipped()) &&
|
||||
(LightTrialClear || Trial::LightTrial.IsSkipped());}}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_DEKU_SCRUBS, {[]{return LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || randoCtx->GetTrial(Rando::FOREST_TRIAL)->IsSkipped()) &&
|
||||
(FireTrialClear || randoCtx->GetTrial(Rando::FIRE_TRIAL)->IsSkipped()) &&
|
||||
(WaterTrialClear || randoCtx->GetTrial(Rando::WATER_TRIAL)->IsSkipped()) &&
|
||||
(ShadowTrialClear || randoCtx->GetTrial(Rando::SHADOW_TRIAL)->IsSkipped()) &&
|
||||
(SpiritTrialClear || randoCtx->GetTrial(Rando::SPIRIT_TRIAL)->IsSkipped()) &&
|
||||
(LightTrialClear || randoCtx->GetTrial(Rando::LIGHT_TRIAL)->IsSkipped());}}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_DEKU_SCRUBS, {[]{return randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_GANONS_CASTLE_MQ_DEKU_SCRUBS] = Area("Ganon's Castle MQ Deku Scrubs", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
@@ -169,7 +169,7 @@ void AreaTable_Init_GanonsCastle() {
|
||||
|
||||
areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL] = Area("Ganon's Castle MQ Fire Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FireTrialClear, {[]{return CanUse(RG_GORON_TUNIC) && CanUse(RG_GOLDEN_GAUNTLETS) && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_LONGSHOT) || HoverBoots || (LogicFireTrialMQ && CanUse(RG_HOOKSHOT)));}}),
|
||||
EventAccess(&FireTrialClear, {[]{return CanUse(RG_GORON_TUNIC) && CanUse(RG_GOLDEN_GAUNTLETS) && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_LONGSHOT) || HoverBoots || (randoCtx->GetTrickOption(RT_GANON_MQ_FIRE_TRIAL) && CanUse(RG_HOOKSHOT)));}}),
|
||||
//Trick: CanUse(RG_GORON_TUNIC) && CanUse(RG_GOLDEN_GAUNTLETS) && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_LONGSHOT) || HoverBoots || (LogicFireTrialMQ && CanUse(RG_HOOKSHOT)))
|
||||
}, {}, {});
|
||||
|
||||
@@ -184,32 +184,32 @@ void AreaTable_Init_GanonsCastle() {
|
||||
|
||||
areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL] = Area("Ganon's Castle MQ Shadow Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ShadowTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)));}}),
|
||||
EventAccess(&ShadowTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || randoCtx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL))));}}),
|
||||
//Trick: IsAdult && CanUse(RG_LIGHT_ARROWS) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)))
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, {[]{return IsAdult && ((Bow && (CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS))) || (CanUse(RG_HOVER_BOOTS) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HasExplosives || GoronBracelet || CanUse(RG_DINS_FIRE))));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, {[]{return IsAdult && Bow && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, {[]{return IsAdult && ((Bow && (CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS))) || (CanUse(RG_HOVER_BOOTS) && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH)) && (HasExplosives || GoronBracelet || CanUse(RG_DINS_FIRE))));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, {[]{return IsAdult && Bow && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || randoCtx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL))));}}),
|
||||
//Trick: IsAdult && Bow && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)))
|
||||
}, {});
|
||||
|
||||
areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL] = Area("Ganon's Castle MQ Spirit Castle", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&SpiritTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && Hammer && HasBombchus && ((FireArrows && MirrorShield) || SunlightArrows);}}),
|
||||
EventAccess(&NutPot, {[]{return NutPot || (Hammer && HasBombchus && IsAdult && ((CanUse(RG_FIRE_ARROWS) && MirrorShield) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS))));}}),
|
||||
EventAccess(&SpiritTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && Hammer && HasBombchus && ((FireArrows && MirrorShield) || randoCtx->GetOption(RSK_SUNLIGHT_ARROWS));}}),
|
||||
EventAccess(&NutPot, {[]{return NutPot || (Hammer && HasBombchus && IsAdult && ((CanUse(RG_FIRE_ARROWS) && MirrorShield) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, {[]{return IsAdult && (Bow || LogicRustedSwitches) && Hammer;}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return IsAdult && (Bow || LogicRustedSwitches) && Hammer && HasBombchus && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, {[]{return IsAdult && (Bow || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && Hammer;}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return IsAdult && (Bow || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && Hammer && HasBombchus && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}),
|
||||
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}),
|
||||
}, {});
|
||||
|
||||
areaTable[RR_GANONS_CASTLE_MQ_LIGHT_TRIAL] = Area("Ganon's Castle MQ Light Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&LightTrialClear, {[]{return IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD)) && CanUse(RG_LIGHT_ARROWS) && SmallKeys(RR_GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (Hookshot || LogicLightTrialMQ);}}),
|
||||
EventAccess(&LightTrialClear, {[]{return IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD)) && CanUse(RG_LIGHT_ARROWS) && SmallKeys(RR_GANONS_CASTLE, 3) && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH)) && (Hookshot || randoCtx->GetTrickOption(RT_GANON_MQ_LIGHT_TRIAL));}}),
|
||||
//Trick: IsAdult && CanUse(RG_LIGHT_ARROWS) && SmallKeys(RR_GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (Hookshot || LogicLightTrialMQ)
|
||||
}, {
|
||||
//Locations
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_GerudoTrainingGrounds() {
|
||||
/*--------------------------
|
||||
@@ -12,15 +12,15 @@ void AreaTable_Init_GerudoTrainingGrounds() {
|
||||
---------------------------*/
|
||||
areaTable[RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY] = Area("Gerudo Training Grounds Entryway", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_LOBBY, {[]{return Dungeon::GerudoTrainingGrounds.IsVanilla();}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY, {[]{return Dungeon::GerudoTrainingGrounds.IsMQ();}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_LOBBY, {[]{return randoCtx->GetDungeon(GERUDO_TRAINING_GROUNDS)->IsVanilla();}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY, {[]{return randoCtx->GetDungeon(GERUDO_TRAINING_GROUNDS)->IsMQ();}}),
|
||||
Entrance(RR_GERUDO_FORTRESS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::GerudoTrainingGrounds.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(GERUDO_TRAINING_GROUNDS)->IsVanilla()) {
|
||||
areaTable[RR_GERUDO_TRAINING_GROUNDS_LOBBY] = Area("Gerudo Training Grounds Lobby", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, {[]{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT);}}),
|
||||
@@ -30,14 +30,14 @@ void AreaTable_Init_GerudoTrainingGrounds() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (CanUse(RG_HOOKSHOT) || LogicGtgWithoutHookshot);}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (CanUse(RG_HOOKSHOT) || randoCtx->GetTrickOption(RT_GTG_WITHOUT_HOOKSHOT));}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_LAVA_ROOM, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_LOBBY, []{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && HasExplosives;});}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE] = Area("Gerudo Training Grounds Central Maze", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 3) && (LogicLensGtg || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 3) && (randoCtx->GetTrickOption(RT_LENS_GTG) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 4);}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 6);}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 7);}}),
|
||||
@@ -70,7 +70,7 @@ void AreaTable_Init_GerudoTrainingGrounds() {
|
||||
areaTable[RR_GERUDO_TRAINING_GROUNDS_HAMMER_ROOM] = Area("Gerudo Training Grounds Hammer Room", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, {[]{return CanAdultAttack || CanChildAttack;}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, {[]{return CanUse(RG_MEGATON_HAMMER) || (CanTakeDamage && LogicFlamingChests);}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, {[]{return CanUse(RG_MEGATON_HAMMER) || (CanTakeDamage && randoCtx->GetTrickOption(RT_FLAMING_CHESTS));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, {[]{return CanUse(RG_MEGATON_HAMMER) && CanUse(RG_FAIRY_BOW);}}),
|
||||
@@ -98,8 +98,8 @@ void AreaTable_Init_GerudoTrainingGrounds() {
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, {[]{return CanJumpslash;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER, {[]{return (LogicLensGtg || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOOKSHOT) || (LogicGtgFakeWall && CanUse(RG_HOVER_BOOTS)));}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM, {[]{return (LogicLensGtg || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOOKSHOT) || (LogicGtgFakeWall && CanUse(RG_HOVER_BOOTS))) && CanUse(RG_SILVER_GAUNTLETS);}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER, {[]{return (randoCtx->GetTrickOption(RT_LENS_GTG) || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_GTG_FAKE_WALL) && CanUse(RG_HOVER_BOOTS)));}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM, {[]{return (randoCtx->GetTrickOption(RT_LENS_GTG) || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_GTG_FAKE_WALL) && CanUse(RG_HOVER_BOOTS))) && CanUse(RG_SILVER_GAUNTLETS);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM] = Area("Gerudo Training Grounds Like Like Room", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -114,12 +114,12 @@ void AreaTable_Init_GerudoTrainingGrounds() {
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::GerudoTrainingGrounds.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(GERUDO_TRAINING_GROUNDS)->IsMQ()) {
|
||||
areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY] = Area("Gerudo Training Grounds MQ Lobby", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, {[]{return LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_GTG_MQ) || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 1);}}),
|
||||
@@ -151,7 +151,7 @@ void AreaTable_Init_GerudoTrainingGrounds() {
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || HasExplosives;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, {[]{return (IsAdult && CanUse(RG_LONGSHOT)) || LogicGtgMQWithoutHookshot || (LogicGtgMQWithHookshot && IsAdult && CanUse(RG_HOOKSHOT));}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, {[]{return (IsAdult && CanUse(RG_LONGSHOT)) || randoCtx->GetTrickOption(RT_GTG_MQ_WIHTOUT_HOOKSHOT) || (randoCtx->GetTrickOption(RT_GTG_MQ_WITH_HOOKSHOT) && IsAdult && CanUse(RG_HOOKSHOT));}}),
|
||||
//Trick: (IsAdult && CanUse(RG_LONGSHOT)) || LogicGtgMQWithoutHookshot || (LogicGtgMQWithHookshot && IsAdult && CanUse(RG_HOOKSHOT))
|
||||
});
|
||||
|
||||
@@ -164,7 +164,7 @@ void AreaTable_Init_GerudoTrainingGrounds() {
|
||||
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, {[]{return CanUse(RG_SILVER_GAUNTLETS) && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, {[]{return IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (LogicGtgFakeWall && IsAdult && CanUse(RG_HOVER_BOOTS)));}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, {[]{return IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (randoCtx->GetTrickOption(RT_LENS_GTG_MQ) || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_GTG_FAKE_WALL) && IsAdult && CanUse(RG_HOVER_BOOTS)));}}),
|
||||
//Trick: IsAdult && (LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (LogicGtgFakeWall && IsAdult && CanUse(RG_HOVER_BOOTS)))
|
||||
});
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../../entrance.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_GerudoValley() {
|
||||
areaTable[RR_GERUDO_VALLEY] = Area("Gerudo Valley", "Gerudo Valley", RHT_GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
|
||||
@@ -18,7 +18,7 @@ void AreaTable_Init_GerudoValley() {
|
||||
Entrance(RR_GV_UPPER_STREAM, {[]{return true;}}),
|
||||
Entrance(RR_GV_CRATE_LEDGE, {[]{return IsChild || CanUse(RG_LONGSHOT);}}),
|
||||
Entrance(RR_GV_GROTTO_LEDGE, {[]{return true;}}),
|
||||
Entrance(RR_GV_FORTRESS_SIDE, {[]{return (IsAdult && (CanRideEpona || CanUse(RG_LONGSHOT) || GerudoFortress.Is(GERUDOFORTRESS_OPEN) || CarpenterRescue)) || (IsChild && CanUse(RG_HOOKSHOT));}}),
|
||||
Entrance(RR_GV_FORTRESS_SIDE, {[]{return (IsAdult && (CanRideEpona || CanUse(RG_LONGSHOT) || randoCtx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_OPEN) || CarpenterRescue)) || (IsChild && CanUse(RG_HOOKSHOT));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_GV_UPPER_STREAM] = Area("GV Upper Stream", "Gerudo Valley", RHT_GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
|
||||
@@ -69,7 +69,7 @@ void AreaTable_Init_GerudoValley() {
|
||||
//Exits
|
||||
Entrance(RR_GERUDO_FORTRESS, {[]{return true;}}),
|
||||
Entrance(RR_GV_UPPER_STREAM, {[]{return true;}}),
|
||||
Entrance(RR_GERUDO_VALLEY, {[]{return IsChild || CanRideEpona || CanUse(RG_LONGSHOT) || GerudoFortress.Is(GERUDOFORTRESS_OPEN) || CarpenterRescue;}}),
|
||||
Entrance(RR_GERUDO_VALLEY, {[]{return IsChild || CanRideEpona || CanUse(RG_LONGSHOT) || randoCtx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_OPEN) || CarpenterRescue;}}),
|
||||
Entrance(RR_GV_CARPENTER_TENT, {[]{return IsAdult;}}),
|
||||
Entrance(RR_GV_STORMS_GROTTO, {[]{return IsAdult && CanOpenStormGrotto;}}),
|
||||
Entrance(RR_GV_CRATE_LEDGE, {[]{return false;}}),
|
||||
@@ -105,26 +105,26 @@ void AreaTable_Init_GerudoValley() {
|
||||
LocationAccess(RC_GF_HBA_1000_POINTS, {[]{return GerudoToken && CanRideEpona && Bow && AtDay;}}),
|
||||
LocationAccess(RC_GF_HBA_1500_POINTS, {[]{return GerudoToken && CanRideEpona && Bow && AtDay;}}),
|
||||
LocationAccess(RC_GF_NORTH_F1_CARPENTER, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
|
||||
LocationAccess(RC_GF_NORTH_F2_CARPENTER, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || LogicGerudoKitchen);}}),
|
||||
LocationAccess(RC_GF_NORTH_F2_CARPENTER, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || randoCtx->GetTrickOption(RT_GF_KITCHEN));}}),
|
||||
LocationAccess(RC_GF_SOUTH_F1_CARPENTER, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
|
||||
LocationAccess(RC_GF_SOUTH_F2_CARPENTER, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
|
||||
LocationAccess(RC_GF_GERUDO_MEMBERSHIP_CARD, {[]{return CanFinishGerudoFortress;}}),
|
||||
LocationAccess(RC_GF_GS_ARCHERY_RANGE, {[]{return IsAdult && HookshotOrBoomerang && GerudoToken && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_GF_GS_TOP_FLOOR, {[]{return IsAdult && AtNight && (CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || LogicGerudoKitchen || LogicGFJump) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_GF_GS_TOP_FLOOR, {[]{return IsAdult && AtNight && (CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || randoCtx->GetTrickOption(RT_GF_KITCHEN) || randoCtx->GetTrickOption(RT_GF_JUMP)) && CanGetNightTimeGS;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_GV_FORTRESS_SIDE, {[]{return true;}}),
|
||||
Entrance(RR_GF_OUTSIDE_GATE, {[]{return GF_GateOpen;}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return GtG_GateOpen && (IsAdult || ShuffleDungeonEntrances);}}),
|
||||
Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return GtG_GateOpen && (IsAdult || randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}}),
|
||||
Entrance(RR_GF_STORMS_GROTTO, {[]{return IsAdult && CanOpenStormGrotto;}}),
|
||||
});
|
||||
|
||||
areaTable[RR_GF_OUTSIDE_GATE] = Area("GF Outside Gate", "Gerudo Fortress", RHT_GERUDO_FORTRESS, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&GF_GateOpen, {[]{return IsAdult && GerudoToken && (ShuffleGerudoToken || ShuffleOverworldEntrances /*|| ShuffleSpecialIndoorEntrances*/);}}),
|
||||
EventAccess(&GF_GateOpen, {[]{return IsAdult && GerudoToken && (randoCtx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD) || randoCtx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) /*|| ShuffleSpecialIndoorEntrances*/);}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_GERUDO_FORTRESS, {[]{return (IsAdult && (Hookshot || !ShuffleOverworldEntrances)) || GF_GateOpen;}}),
|
||||
Entrance(RR_GERUDO_FORTRESS, {[]{return (IsAdult && (Hookshot || !randoCtx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES))) || GF_GateOpen;}}),
|
||||
Entrance(RR_WASTELAND_NEAR_FORTRESS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
@@ -139,7 +139,7 @@ void AreaTable_Init_GerudoValley() {
|
||||
areaTable[RR_WASTELAND_NEAR_FORTRESS] = Area("Wasteland Near Fortress", "Haunted Wasteland", RHT_HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_GF_OUTSIDE_GATE, {[]{return true;}}),
|
||||
Entrance(RR_HAUNTED_WASTELAND, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT) || LogicWastelandCrossing;}}),
|
||||
Entrance(RR_HAUNTED_WASTELAND, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT) || randoCtx->GetTrickOption(RT_HW_CROSSING);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_HAUNTED_WASTELAND] = Area("Haunted Wasteland", "Haunted Wasteland", RHT_HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {
|
||||
@@ -153,14 +153,14 @@ void AreaTable_Init_GerudoValley() {
|
||||
LocationAccess(RC_WASTELAND_GS, {[]{return HookshotOrBoomerang;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_WASTELAND_NEAR_COLOSSUS, {[]{return LogicLensWasteland || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
Entrance(RR_WASTELAND_NEAR_FORTRESS, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT) || LogicWastelandCrossing;}}),
|
||||
Entrance(RR_WASTELAND_NEAR_COLOSSUS, {[]{return randoCtx->GetTrickOption(RT_LENS_HW) || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
Entrance(RR_WASTELAND_NEAR_FORTRESS, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT) || randoCtx->GetTrickOption(RT_HW_CROSSING);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_WASTELAND_NEAR_COLOSSUS] = Area("Wasteland Near Colossus", "Haunted Wasteland", RHT_HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}),
|
||||
Entrance(RR_HAUNTED_WASTELAND, {[]{return LogicReverseWasteland || false;}}),
|
||||
Entrance(RR_HAUNTED_WASTELAND, {[]{return randoCtx->GetTrickOption(RT_HW_REVERSE) || false;}}),
|
||||
});
|
||||
|
||||
areaTable[RR_DESERT_COLOSSUS] = Area("Desert Colossus", "Desert Colossus", RHT_DESERT_COLOSSUS, DAY_NIGHT_CYCLE, {
|
||||
@@ -172,7 +172,7 @@ void AreaTable_Init_GerudoValley() {
|
||||
LocationAccess(RC_COLOSSUS_FREESTANDING_POH, {[]{return IsAdult && CanPlantBean(RR_DESERT_COLOSSUS);}}),
|
||||
LocationAccess(RC_COLOSSUS_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
|
||||
LocationAccess(RC_COLOSSUS_GS_TREE, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_COLOSSUS_GS_HILL, {[]{return IsAdult && AtNight && ((CanPlantBean(RR_DESERT_COLOSSUS) && CanAdultAttack) || CanUse(RG_LONGSHOT) || (LogicColossusGS && CanUse(RG_HOOKSHOT))) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_COLOSSUS_GS_HILL, {[]{return IsAdult && AtNight && ((CanPlantBean(RR_DESERT_COLOSSUS) && CanAdultAttack) || CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_COLOSSUS_GS) && CanUse(RG_HOOKSHOT))) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_COLOSSUS_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../../entrance.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_HyruleField() {
|
||||
areaTable[RR_HYRULE_FIELD] = Area("Hyrule Field", "Hyrule Field", RHT_HYRULE_FIELD, DAY_NIGHT_CYCLE, {
|
||||
@@ -115,7 +115,7 @@ void AreaTable_Init_HyruleField() {
|
||||
LocationAccess(RC_LH_SUN, {[]{return IsAdult && WaterTempleClear && CanUse(RG_FAIRY_BOW);}}),
|
||||
LocationAccess(RC_LH_FREESTANDING_POH, {[]{return IsAdult && (CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA));}}),
|
||||
LocationAccess(RC_LH_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
|
||||
LocationAccess(RC_LH_GS_LAB_WALL, {[]{return IsChild && (HookshotOrBoomerang || (LogicLabWallGS && CanJumpslash)) && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_LH_GS_LAB_WALL, {[]{return IsChild && (HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_LH_LAB_WALL_GS) && CanJumpslash)) && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_LH_GS_SMALL_ISLAND, {[]{return IsChild && CanChildAttack && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_LH_GS_TREE, {[]{return IsAdult && CanUse(RG_LONGSHOT) && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_LH_LAB_GOSSIP_STONE, {[]{return true;}}),
|
||||
@@ -128,7 +128,7 @@ void AreaTable_Init_HyruleField() {
|
||||
Entrance(RR_LH_OWL_FLIGHT, {[]{return IsChild;}}),
|
||||
Entrance(RR_LH_FISHING_ISLAND, {[]{return IsChild || CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA) || WaterTempleClear;}}),
|
||||
Entrance(RR_LH_LAB, {[]{return true;}}),
|
||||
Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_HOOKSHOT) && ((CanUse(RG_IRON_BOOTS) || (LogicWaterHookshotEntry && ProgressiveScale >= 2)) || (IsAdult && CanUse(RG_LONGSHOT) && ProgressiveScale >= 2));}}),
|
||||
Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_HOOKSHOT) && ((CanUse(RG_IRON_BOOTS) || (randoCtx->GetTrickOption(RT_LH_WATER_HOOKSHOT) && ProgressiveScale >= 2)) || (IsAdult && CanUse(RG_LONGSHOT) && ProgressiveScale >= 2));}}),
|
||||
Entrance(RR_LH_GROTTO, {[]{return true;}}),
|
||||
});
|
||||
|
||||
@@ -148,7 +148,7 @@ void AreaTable_Init_HyruleField() {
|
||||
EventAccess(&EyedropsAccess, {[]{return EyedropsAccess || (IsAdult && (EyeballFrogAccess || (EyeballFrog && DisableTradeRevert)));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_LH_LAB_DIVE, {[]{return ProgressiveScale >= 2 || (LogicLabDiving && CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT));}}),
|
||||
LocationAccess(RC_LH_LAB_DIVE, {[]{return ProgressiveScale >= 2 || (randoCtx->GetTrickOption(RT_LH_LAB_DIVING) && CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT));}}),
|
||||
LocationAccess(RC_LH_TRADE_FROG, {[]{return IsAdult && EyeballFrog;}}),
|
||||
LocationAccess(RC_LH_GS_LAB_CRATE, {[]{return CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT);}}),
|
||||
}, {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_IceCavern() {
|
||||
/*--------------------------
|
||||
@@ -12,15 +12,15 @@ void AreaTable_Init_IceCavern() {
|
||||
---------------------------*/
|
||||
areaTable[RR_ICE_CAVERN_ENTRYWAY] = Area("Ice Cavern Entryway", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_ICE_CAVERN_BEGINNING, {[]{return Dungeon::IceCavern.IsVanilla();}}),
|
||||
Entrance(RR_ICE_CAVERN_MQ_BEGINNING, {[]{return Dungeon::IceCavern.IsMQ() && CanUseProjectile;}}),
|
||||
Entrance(RR_ICE_CAVERN_BEGINNING, {[]{return randoCtx->GetDungeon(ICE_CAVERN)->IsVanilla();}}),
|
||||
Entrance(RR_ICE_CAVERN_MQ_BEGINNING, {[]{return randoCtx->GetDungeon(ICE_CAVERN)->IsMQ() && CanUseProjectile;}}),
|
||||
Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::IceCavern.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(ICE_CAVERN)->IsVanilla()) {
|
||||
areaTable[RR_ICE_CAVERN_BEGINNING] = Area("Ice Cavern Beginning", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_ICE_CAVERN_ENTRYWAY, {[]{return true;}}),
|
||||
@@ -39,14 +39,14 @@ void AreaTable_Init_IceCavern() {
|
||||
LocationAccess(RC_ICE_CAVERN_FREESTANDING_POH, {[]{return BlueFire;}}),
|
||||
LocationAccess(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, {[]{return HookshotOrBoomerang;}}),
|
||||
LocationAccess(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, {[]{return BlueFire && HookshotOrBoomerang;}}),
|
||||
LocationAccess(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, {[]{return BlueFire && (HookshotOrBoomerang || (LogicIceBlockGS && IsAdult && CanUse(RG_HOVER_BOOTS)));}}),
|
||||
LocationAccess(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, {[]{return BlueFire && (HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_ICE_BLOCK_GS) && IsAdult && CanUse(RG_HOVER_BOOTS)));}}),
|
||||
}, {});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::IceCavern.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(ICE_CAVERN)->IsMQ()) {
|
||||
areaTable[RR_ICE_CAVERN_MQ_BEGINNING] = Area("Ice Cavern MQ Beginning", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return true;}}),
|
||||
@@ -71,7 +71,7 @@ void AreaTable_Init_IceCavern() {
|
||||
LocationAccess(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, {[]{return IsAdult && (CanJumpslash || CanUse(RG_MEGATON_HAMMER));}}),
|
||||
LocationAccess(RC_SHEIK_IN_ICE_CAVERN, {[]{return IsAdult && (CanJumpslash || CanUse(RG_MEGATON_HAMMER));}}),
|
||||
LocationAccess(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, {[]{return CanAdultAttack || CanChildAttack;}}),
|
||||
LocationAccess(RC_ICE_CAVERN_MQ_GS_SCARECROW, {[]{return CanUse(RG_SCARECROW) || (HoverBoots && CanUse(RG_LONGSHOT)) || (LogicIceMQScarecrow && IsAdult);}}),
|
||||
LocationAccess(RC_ICE_CAVERN_MQ_GS_SCARECROW, {[]{return CanUse(RG_SCARECROW) || (HoverBoots && CanUse(RG_LONGSHOT)) || (randoCtx->GetTrickOption(RT_ICE_MQ_SCARECROW) && IsAdult);}}),
|
||||
//Tricks: (CanUse(RG_SCARECROW) || (HoverBoots && CanUse(RG_LONGSHOT)) || LogicIceMQScarecrow) && IsAdult
|
||||
}, {});
|
||||
|
||||
@@ -79,7 +79,7 @@ void AreaTable_Init_IceCavern() {
|
||||
//Locations
|
||||
LocationAccess(RC_ICE_CAVERN_MQ_COMPASS_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_ICE_CAVERN_MQ_FREESTANDING_POH, {[]{return HasExplosives;}}),
|
||||
LocationAccess(RC_ICE_CAVERN_MQ_GS_RED_ICE, {[]{return CanPlay(SongOfTime) || LogicIceMQRedIceGS;}}),
|
||||
LocationAccess(RC_ICE_CAVERN_MQ_GS_RED_ICE, {[]{return CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_ICE_MQ_RED_ICE_GS);}}),
|
||||
//Trick: CanPlay(SongOfTime) || LogicIceMQRedIceGS
|
||||
}, {});
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_JabuJabusBelly() {
|
||||
/*--------------------------
|
||||
@@ -12,15 +12,15 @@ void AreaTable_Init_JabuJabusBelly() {
|
||||
---------------------------*/
|
||||
areaTable[RR_JABU_JABUS_BELLY_ENTRYWAY] = Area("Jabu Jabus Belly Entryway", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_BEGINNING, {[]{return Dungeon::JabuJabusBelly.IsVanilla();}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return Dungeon::JabuJabusBelly.IsMQ();}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_BEGINNING, {[]{return randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsVanilla();}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsMQ();}}),
|
||||
Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::JabuJabusBelly.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsVanilla()) {
|
||||
areaTable[RR_JABU_JABUS_BELLY_BEGINNING] = Area("Jabu Jabus Belly Beginning", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}),
|
||||
@@ -32,7 +32,7 @@ void AreaTable_Init_JabuJabusBelly() {
|
||||
Entrance(RR_JABU_JABUS_BELLY_BEGINNING, {[]{return true;}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_LIFT_LOWER, {[]{return true;}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, {[]{return HasAccessTo(RR_JABU_JABUS_BELLY_LIFT_UPPER) || (LogicJabuBossHover && IsAdult && CanUse(RG_HOVER_BOOTS));}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, {[]{return HasAccessTo(RR_JABU_JABUS_BELLY_LIFT_UPPER) || (randoCtx->GetTrickOption(RT_JABU_BOSS_HOVER) && IsAdult && CanUse(RG_HOVER_BOOTS));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_JABU_JABUS_BELLY_MAIN_UPPER] = Area("Jabu Jabus Belly Main Upper", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
@@ -76,7 +76,7 @@ void AreaTable_Init_JabuJabusBelly() {
|
||||
|
||||
areaTable[RR_JABU_JABUS_BELLY_LIFT_LOWER] = Area("Jabu Jabus Belly Lift Lower", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_DEKU_SCRUB, {[]{return (IsChild || CanDive || LogicJabuAlcoveJumpDive || CanUse(RG_IRON_BOOTS)) && CanStunDeku;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_DEKU_SCRUB, {[]{return (IsChild || CanDive || randoCtx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE) || CanUse(RG_IRON_BOOTS)) && CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_SHABOMB_CORRIDOR, {[]{return true;}}),
|
||||
@@ -154,14 +154,14 @@ void AreaTable_Init_JabuJabusBelly() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return CanUse(RG_BOOMERANG) || (LogicJabuNearBossRanged && ((IsAdult && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW))) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT)))) || (LogicJabuNearBossExplosives && (HasBombchus || (IsAdult && CanUse(RG_HOVER_BOOTS) && Bombs)));}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return CanUse(RG_BOOMERANG) || (randoCtx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && ((IsAdult && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW))) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT)))) || (randoCtx->GetTrickOption(RT_JABU_NEAR_BOSS_EXPLOSIVES) && (HasBombchus || (IsAdult && CanUse(RG_HOVER_BOOTS) && Bombs)));}}),
|
||||
});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::JabuJabusBelly.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsMQ()) {
|
||||
areaTable[RR_JABU_JABUS_BELLY_MQ_BEGINNING] = Area("Jabu Jabus Belly MQ Beginning", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&NutPot, {[]{return true;}}),
|
||||
@@ -184,7 +184,7 @@ void AreaTable_Init_JabuJabusBelly() {
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(RG_BOOMERANG));}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_JABU_MQ_SOT_GS) && IsChild && CanUse(RG_BOOMERANG));}}),
|
||||
//Trick: CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(RG_BOOMERANG))
|
||||
}, {
|
||||
//Exits
|
||||
@@ -196,7 +196,7 @@ void AreaTable_Init_JabuJabusBelly() {
|
||||
//Locations
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, {[]{return Sticks || CanUse(RG_DINS_FIRE);}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, {[]{return (LogicLensJabuMQ || CanUse(RG_LENS_OF_TRUTH)) || Here(RR_JABU_JABUS_BELLY_MQ_MAIN, []{return IsAdult && CanUse(RG_HOVER_BOOTS) && CanUse(RG_HOOKSHOT);});}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, {[]{return (randoCtx->GetTrickOption(RT_LENS_JABU_MQ) || CanUse(RG_LENS_OF_TRUTH)) || Here(RR_JABU_JABUS_BELLY_MQ_MAIN, []{return IsAdult && CanUse(RG_HOVER_BOOTS) && CanUse(RG_HOOKSHOT);});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}),
|
||||
@@ -225,8 +225,8 @@ void AreaTable_Init_JabuJabusBelly() {
|
||||
Area("Jabu Jabus Belly Boss Entryway", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {},
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, { [] { return Dungeon::JabuJabusBelly.IsVanilla(); } }),
|
||||
Entrance(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA, { [] { return Dungeon::JabuJabusBelly.IsMQ(); } }),
|
||||
Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, { [] { return randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsVanilla(); } }),
|
||||
Entrance(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA, { [] { return randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsMQ(); } }),
|
||||
Entrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, { [] { return true; } }),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../../entrance.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_Kakariko() {
|
||||
areaTable[RR_KAKARIKO_VILLAGE] = Area("Kakariko Village", "Kakariko Village", RHT_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&CojiroAccess, {[]{return CojiroAccess || (IsAdult && WakeUpAdultTalon);}}),
|
||||
EventAccess(&BugRock, {[]{return true;}}),
|
||||
EventAccess(&KakarikoVillageGateOpen, {[]{return KakarikoVillageGateOpen || (IsChild && (ZeldasLetter || OpenKakariko.Is(OPENKAKARIKO_OPEN)));}}),
|
||||
EventAccess(&KakarikoVillageGateOpen, {[]{return KakarikoVillageGateOpen || (IsChild && (ZeldasLetter || randoCtx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN)));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SHEIK_IN_KAKARIKO, {[]{return IsAdult && ForestMedallion && FireMedallion && WaterMedallion;}}),
|
||||
@@ -21,7 +21,7 @@ void AreaTable_Init_Kakariko() {
|
||||
LocationAccess(RC_KAK_GS_SKULLTULA_HOUSE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_KAK_GS_GUARDS_HOUSE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_KAK_GS_TREE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_KAK_GS_WATCHTOWER, {[]{return IsChild && (Slingshot || HasBombchus || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT) || (LogicKakarikoTowerGS && CanJumpslash)) && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_KAK_GS_WATCHTOWER, {[]{return IsChild && (Slingshot || HasBombchus || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_KAK_TOWER_GS) && CanJumpslash)) && AtNight && CanGetNightTimeGS;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
|
||||
@@ -31,12 +31,12 @@ void AreaTable_Init_Kakariko() {
|
||||
Entrance(RR_KAK_WINDMILL, {[]{return true;}}),
|
||||
Entrance(RR_KAK_BAZAAR, {[]{return IsAdult && AtDay;}}),
|
||||
Entrance(RR_KAK_SHOOTING_GALLERY, {[]{return IsAdult && AtDay;}}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return DrainWell && (IsChild || ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF));}}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return DrainWell && (IsChild || randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF));}}),
|
||||
Entrance(RR_KAK_POTION_SHOP_FRONT, {[]{return AtDay || IsChild;}}),
|
||||
Entrance(RR_KAK_REDEAD_GROTTO, {[]{return CanOpenBombGrotto;}}),
|
||||
Entrance(RR_KAK_IMPAS_LEDGE, {[]{return (IsChild && AtDay) || CanUse(RG_HOOKSHOT) || (IsAdult && LogicVisibleCollision);}}),
|
||||
Entrance(RR_KAK_ROOFTOP, {[]{return CanUse(RG_HOOKSHOT) || (LogicManOnRoof && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)));}}),
|
||||
Entrance(RR_KAK_IMPAS_ROOFTOP, {[]{return CanUse(RG_HOOKSHOT) || (LogicKakarikoRooftopGS && CanUse(RG_HOVER_BOOTS));}}),
|
||||
Entrance(RR_KAK_IMPAS_LEDGE, {[]{return (IsChild && AtDay) || CanUse(RG_HOOKSHOT) || (IsAdult && randoCtx->GetTrickOption(RT_VISIBLE_COLLISION));}}),
|
||||
Entrance(RR_KAK_ROOFTOP, {[]{return CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_KAK_MAN_ON_ROOF) && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)));}}),
|
||||
Entrance(RR_KAK_IMPAS_ROOFTOP, {[]{return CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_KAK_ROOFTOP_GS) && CanUse(RG_HOVER_BOOTS));}}),
|
||||
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
|
||||
Entrance(RR_KAK_BEHIND_GATE, {[]{return IsAdult || (KakarikoVillageGateOpen);}}),
|
||||
});
|
||||
@@ -118,7 +118,7 @@ void AreaTable_Init_Kakariko() {
|
||||
EventAccess(&DrainWell, {[]{return DrainWell || (IsChild && CanPlay(SongOfStorms));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_KAK_WINDMILL_FREESTANDING_POH, {[]{return CanUse(RG_BOOMERANG) || DampesWindmillAccess || (IsAdult && LogicAdultWindmillPoH) || (IsChild && CanJumpslash && LogicChildWindmillPoH);}}),
|
||||
LocationAccess(RC_KAK_WINDMILL_FREESTANDING_POH, {[]{return CanUse(RG_BOOMERANG) || DampesWindmillAccess || (IsAdult && randoCtx->GetTrickOption(RT_KAK_ADULT_WINDMILL_POH)) || (IsChild && CanJumpslash && randoCtx->GetTrickOption(RT_KAK_CHILD_WINDMILL_POH));}}),
|
||||
//PoH as child not added to trick options yet (needs uncommenting in randomizer_tricks.cpp)
|
||||
LocationAccess(RC_SONG_FROM_WINDMILL, {[]{return IsAdult && Ocarina;}}),
|
||||
}, {
|
||||
@@ -212,7 +212,7 @@ void AreaTable_Init_Kakariko() {
|
||||
EventAccess(&BugRock, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GRAVEYARD_FREESTANDING_POH, {[]{return (IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || CanUse(RG_LONGSHOT) || (LogicGraveyardPoH && CanUse(RG_BOOMERANG));}}),
|
||||
LocationAccess(RC_GRAVEYARD_FREESTANDING_POH, {[]{return (IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_GY_POH) && CanUse(RG_BOOMERANG));}}),
|
||||
LocationAccess(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, {[]{return IsChild && AtNight;}}), //TODO: This needs to change
|
||||
LocationAccess(RC_GRAVEYARD_GS_WALL, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_GRAVEYARD_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
|
||||
@@ -260,7 +260,7 @@ void AreaTable_Init_Kakariko() {
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_GRAVEYARD_HOOKSHOT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, {[]{return IsAdult || LogicChildDampeRacePoH;}}),
|
||||
LocationAccess(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, {[]{return IsAdult || randoCtx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
|
||||
@@ -284,12 +284,12 @@ void AreaTable_Init_Kakariko() {
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_DINS_FIRE) || (LogicShadowFireArrowEntry && IsAdult && CanUse(RG_FIRE_ARROWS));}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_GY_SHADOW_FIRE_ARROWS) && IsAdult && CanUse(RG_FIRE_ARROWS));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_KAK_BEHIND_GATE] = Area("Kak Behind Gate", "Kakariko Village", RHT_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_KAKARIKO_VILLAGE, {[]{return IsAdult || LogicVisibleCollision || KakarikoVillageGateOpen || OpenKakariko.Is(OPENKAKARIKO_OPEN);}}),
|
||||
Entrance(RR_KAKARIKO_VILLAGE, {[]{return IsAdult || randoCtx->GetTrickOption(RT_VISIBLE_COLLISION) || KakarikoVillageGateOpen || randoCtx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN);}}),
|
||||
Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../../entrance.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_LostWoods() {
|
||||
areaTable[RR_KOKIRI_FOREST] = Area("Kokiri Forest", "Kokiri Forest", RHT_KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, {
|
||||
@@ -14,9 +14,9 @@ void AreaTable_Init_LostWoods() {
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_KF_KOKIRI_SWORD_CHEST, {[]{return IsChild;}}),
|
||||
LocationAccess(RC_KF_GS_KNOW_IT_ALL_HOUSE, {[]{return IsChild && CanChildAttack && AtNight && (HasNightStart || CanLeaveForest || CanPlay(SunsSong)) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_KF_GS_KNOW_IT_ALL_HOUSE, {[]{return IsChild && CanChildAttack && AtNight && (/*TODO: HasNightStart ||*/ CanLeaveForest || CanPlay(SunsSong)) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_KF_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
|
||||
LocationAccess(RC_KF_GS_HOUSE_OF_TWINS, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || (LogicAdultKokiriGS && CanUse(RG_HOVER_BOOTS))) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_KF_GS_HOUSE_OF_TWINS, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_KF_ADULT_GS) && CanUse(RG_HOVER_BOOTS))) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_KF_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
@@ -26,16 +26,16 @@ void AreaTable_Init_LostWoods() {
|
||||
Entrance(RR_KF_HOUSE_OF_TWINS, {[]{return true;}}),
|
||||
Entrance(RR_KF_KNOW_IT_ALL_HOUSE, {[]{return true;}}),
|
||||
Entrance(RR_KF_KOKIRI_SHOP, {[]{return true;}}),
|
||||
Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return IsAdult || OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield;}}),
|
||||
Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return IsAdult || randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || ShowedMidoSwordAndShield;}}),
|
||||
Entrance(RR_THE_LOST_WOODS, {[]{return true;}}),
|
||||
Entrance(RR_LW_BRIDGE_FROM_FOREST, {[]{return IsAdult || OpenForest.IsNot(OPENFOREST_CLOSED) || DekuTreeClear;}}),
|
||||
Entrance(RR_LW_BRIDGE_FROM_FOREST, {[]{return IsAdult || randoCtx->GetOption(RSK_FOREST).IsNot(RO_FOREST_CLOSED) || DekuTreeClear;}}),
|
||||
Entrance(RR_KF_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
|
||||
});
|
||||
|
||||
areaTable[RR_KF_OUTSIDE_DEKU_TREE] = Area("KF Outside Deku Tree", "Kokiri Forest", RHT_KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || ((IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_KOKIRI_SWORD)) && !ShuffleEntrances) || (IsChild && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BOOMERANG))));}}),
|
||||
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || ((IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_KOKIRI_SWORD)) && !ShuffleEntrances) || (IsChild && (CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || HasExplosives || CanUse(RG_DINS_FIRE))));}}),
|
||||
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || ((IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_KOKIRI_SWORD)) && !randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES)) || (IsChild && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BOOMERANG))));}}),
|
||||
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || ((IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_KOKIRI_SWORD)) && !randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES)) || (IsChild && (CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || HasExplosives || CanUse(RG_DINS_FIRE))));}}),
|
||||
EventAccess(&ShowedMidoSwordAndShield, {[]{return ShowedMidoSwordAndShield || (IsChild && KokiriSword && DekuShield);}}),
|
||||
}, {
|
||||
//Locations
|
||||
@@ -43,8 +43,8 @@ void AreaTable_Init_LostWoods() {
|
||||
LocationAccess(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return IsChild || (ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF) && (OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield));}}),
|
||||
Entrance(RR_KOKIRI_FOREST, {[]{return IsAdult || OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield;}}),
|
||||
Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return IsChild || (randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && (randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || ShowedMidoSwordAndShield));}}),
|
||||
Entrance(RR_KOKIRI_FOREST, {[]{return IsAdult || randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || ShowedMidoSwordAndShield;}}),
|
||||
});
|
||||
|
||||
areaTable[RR_KF_LINKS_HOUSE] = Area("KF Link's House", "KF Link's House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -131,9 +131,9 @@ void AreaTable_Init_LostWoods() {
|
||||
//Exits
|
||||
Entrance(RR_LW_FOREST_EXIT, {[]{return true;}}),
|
||||
Entrance(RR_GC_WOODS_WARP, {[]{return true;}}),
|
||||
Entrance(RR_LW_BRIDGE, {[]{return CanLeaveForest && ((IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || LogicLostWoodsBridge)) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT));}}),
|
||||
Entrance(RR_LW_BRIDGE, {[]{return CanLeaveForest && ((IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || randoCtx->GetTrickOption(RT_LW_BRIDGE))) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT));}}),
|
||||
Entrance(RR_ZORAS_RIVER, {[]{return CanLeaveForest && (CanDive || CanUse(RG_IRON_BOOTS));}}),
|
||||
Entrance(RR_LW_BEYOND_MIDO, {[]{return IsChild || CanPlay(SariasSong) || LogicMidoBackflip;}}),
|
||||
Entrance(RR_LW_BEYOND_MIDO, {[]{return IsChild || CanPlay(SariasSong) || randoCtx->GetTrickOption(RT_LW_MIDO_BACKFLIP);}}),
|
||||
Entrance(RR_LW_NEAR_SHORTCUTS_GROTTO, {[]{return Here(RR_THE_LOST_WOODS, []{return CanBlastOrSmash;});}}),
|
||||
});
|
||||
|
||||
@@ -144,8 +144,8 @@ void AreaTable_Init_LostWoods() {
|
||||
//Locations
|
||||
LocationAccess(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, {[]{return IsChild && CanStunDeku;}}),
|
||||
LocationAccess(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, {[]{return IsChild && CanStunDeku;}}),
|
||||
LocationAccess(RC_LW_GS_ABOVE_THEATER, {[]{return IsAdult && AtNight && ((CanPlantBean(RR_LW_BEYOND_MIDO) && CanAdultAttack) || (LogicLostWoodsGSBean && CanUse(RG_HOOKSHOT) && (CanUse(RG_LONGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || HasBombchus || CanUse(RG_DINS_FIRE)))) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, {[]{return CanPlantBugs && (CanChildAttack || (Scrubsanity.Is(SCRUBSANITY_OFF) && DekuShield));}}),
|
||||
LocationAccess(RC_LW_GS_ABOVE_THEATER, {[]{return IsAdult && AtNight && ((CanPlantBean(RR_LW_BEYOND_MIDO) && CanAdultAttack) || (randoCtx->GetTrickOption(RT_LW_GS_BEAN) && CanUse(RG_HOOKSHOT) && (CanUse(RG_LONGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || HasBombchus || CanUse(RG_DINS_FIRE)))) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, {[]{return CanPlantBugs && (CanChildAttack || (randoCtx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF) && DekuShield));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_LW_FOREST_EXIT, {[]{return true;}}),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_ShadowTemple() {
|
||||
/*--------------------------
|
||||
@@ -12,15 +12,15 @@ void AreaTable_Init_ShadowTemple() {
|
||||
---------------------------*/
|
||||
areaTable[RR_SHADOW_TEMPLE_ENTRYWAY] = Area("Shadow Temple Entryway", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_BEGINNING, {[]{return Dungeon::ShadowTemple.IsVanilla() && (LogicLensShadow || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_BEGINNING, {[]{return Dungeon::ShadowTemple.IsMQ() && (LogicLensShadowMQ || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_BEGINNING, {[]{return randoCtx->GetDungeon(SHADOW_TEMPLE)->IsVanilla() && (randoCtx->GetTrickOption(RT_LENS_SHADOW) || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_BEGINNING, {[]{return randoCtx->GetDungeon(SHADOW_TEMPLE)->IsMQ() && (randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
|
||||
Entrance(RR_GRAVEYARD_WARP_PAD_REGION, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::ShadowTemple.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(SHADOW_TEMPLE)->IsVanilla()) {
|
||||
areaTable[RR_SHADOW_TEMPLE_BEGINNING] = Area("Shadow Temple Beginning", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&NutPot, {[]{return true;}}),
|
||||
@@ -53,16 +53,16 @@ void AreaTable_Init_ShadowTemple() {
|
||||
LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanJumpslash;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanJumpslash;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_FREESTANDING_KEY, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && (Bombs || GoronBracelet || (LogicShadowFreestandingKey && HasBombchus));}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && HoverBoots) || GoronBracelet;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && HoverBoots) || GoronBracelet;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_FREESTANDING_KEY, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && (Bombs || GoronBracelet || (randoCtx->GetTrickOption(RT_SHADOW_FREESTANDING_KEY) && HasBombchus));}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, {[]{return CanJumpslash;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (LogicShadowUmbrellaGS && HoverBoots);}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && HoverBoots);}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_WIND_TUNNEL, {[]{return ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && SmallKeys(RR_SHADOW_TEMPLE, 3, 4);}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_WIND_TUNNEL, {[]{return ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && SmallKeys(RR_SHADOW_TEMPLE, 3, 4);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL] = Area("Shadow Temple Wind Tunnel", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -84,18 +84,18 @@ void AreaTable_Init_ShadowTemple() {
|
||||
LocationAccess(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, {[]{return CanAdultAttack;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus)) && SmallKeys(RR_SHADOW_TEMPLE, 5) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}})
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_DISTANT_SCARECROW) || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && HasBombchus)) && SmallKeys(RR_SHADOW_TEMPLE, 5) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}})
|
||||
});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::ShadowTemple.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(SHADOW_TEMPLE)->IsMQ()) {
|
||||
areaTable[RR_SHADOW_TEMPLE_MQ_BEGINNING] = Area("Shadow Temple MQ Beginning", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, {[]{return IsAdult && (CanUse(RG_FIRE_ARROWS) || HoverBoots || (LogicShadowMQGap && CanUse(RG_LONGSHOT)));}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, {[]{return IsAdult && (CanUse(RG_FIRE_ARROWS) || HoverBoots || (randoCtx->GetTrickOption(RT_SHADOW_MQ_GAP) && CanUse(RG_LONGSHOT)));}}),
|
||||
//Trick: IsAdult && (CanUse(RG_FIRE_ARROWS) || HoverBoots || (LogicShadowMQGap && CanUse(RG_LONGSHOT)))
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_DEAD_HAND_AREA, {[]{return HasExplosives && SmallKeys(RR_SHADOW_TEMPLE, 6);}}),
|
||||
});
|
||||
@@ -118,13 +118,13 @@ void AreaTable_Init_ShadowTemple() {
|
||||
|
||||
areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT] = Area("Shadow Temple MQ Upper Huge Pit", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO));}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO));}}),
|
||||
//Trick: CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO));}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO));}}),
|
||||
//Trick: CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, {[]{return HasFireSource || LogicShadowMQHugePit;}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, {[]{return HasFireSource || randoCtx->GetTrickOption(RT_SHADOW_MQ_HUGE_PIT);}}),
|
||||
//Trick: HasFireSource || LogicShadowMQHugePit
|
||||
});
|
||||
|
||||
@@ -132,15 +132,15 @@ void AreaTable_Init_ShadowTemple() {
|
||||
//Locations
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, {[]{return IsAdult && CanUse(RG_LONGSHOT);}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, {[]{return CanJumpslash && HoverBoots && SmallKeys(RR_SHADOW_TEMPLE, 3) && ((LogicLensShadowMQ && LogicLensShadowMQPlatform) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && HoverBoots && SmallKeys(RR_SHADOW_TEMPLE, 3) && Hookshot && ((LogicLensShadowMQ &&
|
||||
LogicLensShadowMQInvisibleBlades && LogicLensShadowMQPlatform) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (LogicShadowUmbrellaGS && HoverBoots);}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && HoverBoots) || GoronBracelet;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && HoverBoots) || GoronBracelet;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, {[]{return CanJumpslash && HoverBoots && SmallKeys(RR_SHADOW_TEMPLE, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && HoverBoots && SmallKeys(RR_SHADOW_TEMPLE, 3) && Hookshot && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) &&
|
||||
randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && HoverBoots);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL, {[]{return HoverBoots && ((LogicLensShadowMQ && LogicLensShadowMQPlatform) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && SmallKeys(RR_SHADOW_TEMPLE, 4);}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL, {[]{return HoverBoots && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && SmallKeys(RR_SHADOW_TEMPLE, 4);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL] = Area("Shadow Temple MQ Wind Tunnel", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
@@ -161,11 +161,11 @@ void AreaTable_Init_ShadowTemple() {
|
||||
areaTable[RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT] = Area("Shadow Temple MQ Beyond Boat", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, {[]{return true;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, {[]{return Bow || (LogicShadowStatue && HasBombchus);}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, {[]{return Bow || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && HasBombchus);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, {[]{return Bow && CanPlay(SongOfTime) && IsAdult && CanUse(RG_LONGSHOT);}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || (LogicShadowStatue && HasBombchus)) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}}),
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && HasBombchus)) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}}),
|
||||
});
|
||||
|
||||
areaTable[RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE] = Area("Shadow Temple MQ Invisible Maze", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -173,7 +173,7 @@ void AreaTable_Init_ShadowTemple() {
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, {[]{return CanUse(RG_DINS_FIRE) && SmallKeys(RR_SHADOW_TEMPLE, 6);}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return CanUse(RG_DINS_FIRE) && SmallKeys(RR_SHADOW_TEMPLE, 6);}}),
|
||||
//below previously returned true
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, {[]{return CanUse(RG_LENS_OF_TRUTH) || LogicLensShadowMQDeadHand;}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, {[]{return CanUse(RG_LENS_OF_TRUTH) || randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_DEADHAND);}}),
|
||||
LocationAccess(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, {[]{return true;}}),
|
||||
}, {});
|
||||
}
|
||||
@@ -185,8 +185,8 @@ void AreaTable_Init_ShadowTemple() {
|
||||
Area("Shadow Temple Boss Entryway", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, { [] { return Dungeon::ShadowTemple.IsVanilla() && false; } }),
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, { [] { return Dungeon::ShadowTemple.IsMQ() && false; } }),
|
||||
Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, { [] { return randoCtx->GetDungeon(SHADOW_TEMPLE)->IsVanilla() && false; } }),
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, { [] { return randoCtx->GetDungeon(SHADOW_TEMPLE)->IsMQ() && false; } }),
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ROOM, { [] { return true; } }),
|
||||
});
|
||||
|
||||
@@ -196,9 +196,9 @@ void AreaTable_Init_ShadowTemple() {
|
||||
// Events
|
||||
EventAccess(&ShadowTempleClear, { [] {
|
||||
return ShadowTempleClear || (HasBossSoul(RG_BONGO_BONGO_SOUL) &&
|
||||
((CanUse(RG_LENS_OF_TRUTH) || LogicLensBongo) &&
|
||||
((CanUse(RG_LENS_OF_TRUTH) || randoCtx->GetTrickOption(RT_LENS_BONGO)) &&
|
||||
(CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) &&
|
||||
(CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || LogicShadowBongo)));
|
||||
(CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || randoCtx->GetTrickOption(RT_SHADOW_BONGO))));
|
||||
} }),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_SpiritTemple() {
|
||||
/*--------------------------
|
||||
@@ -12,15 +12,15 @@ void AreaTable_Init_SpiritTemple() {
|
||||
---------------------------*/
|
||||
areaTable[RR_SPIRIT_TEMPLE_ENTRYWAY] = Area("Spirit Temple Entryway", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_LOBBY, {[]{return Dungeon::SpiritTemple.IsVanilla();}}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, {[]{return Dungeon::SpiritTemple.IsMQ();}}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_LOBBY, {[]{return randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla();}}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, {[]{return randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsMQ();}}),
|
||||
Entrance(RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::SpiritTemple.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla()) {
|
||||
areaTable[RR_SPIRIT_TEMPLE_LOBBY] = Area("Spirit Temple Lobby", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
@@ -33,9 +33,9 @@ void AreaTable_Init_SpiritTemple() {
|
||||
EventAccess(&NutCrate, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot))) && (Sticks || CanUse(RG_DINS_FIRE));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot))) && (Sticks || CanUse(RG_DINS_FIRE));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, {[]{return (Boomerang || Slingshot || (HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_CHILD_CLIMB, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 1);}}),
|
||||
@@ -43,24 +43,24 @@ void AreaTable_Init_SpiritTemple() {
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Area("Child Spirit Temple Climb", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, {[]{return HasProjectile(HasProjectileAge::Both) || CanUse(RG_DINS_FIRE) ||
|
||||
(CanTakeDamage && (CanJumpslash || HasProjectile(HasProjectileAge::Child))) ||
|
||||
(IsChild && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasProjectile(HasProjectileAge::Child)) ||
|
||||
((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && (HasProjectile(HasProjectileAge::Adult) || (CanTakeDamage && CanJumpslash)));}}),
|
||||
((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && (HasProjectile(HasProjectileAge::Adult) || (CanTakeDamage && CanJumpslash)));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return HasExplosives || (SunlightArrows && CanUse(RG_LIGHT_ARROWS));}}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return HasExplosives || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_EARLY_ADULT] = Area("Early Adult Spirit Temple", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_COMPASS_CHEST, {[]{return CanUse(RG_HOOKSHOT) && CanPlay(ZeldasLullaby);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasBombchus || (Bombs && IsAdult && LogicSpiritLowerAdultSwitch)) && (CanUse(RG_HOVER_BOOTS) || CanJumpslash);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasBombchus || (Bombs && IsAdult && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (CanUse(RG_HOVER_BOOTS) || CanJumpslash);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, {[]{return CanPlay(SongOfTime) && (Bow || Hookshot || HasBombchus || (Bombs && LogicSpiritLowerAdultSwitch));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, {[]{return CanPlay(SongOfTime) && (Bow || Hookshot || HasBombchus || (Bombs && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH)));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 1);}}),
|
||||
@@ -68,34 +68,34 @@ void AreaTable_Init_SpiritTemple() {
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Area("Spirit Temple Central Chamber", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MAP_CHEST, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) &&
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MAP_CHEST, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) &&
|
||||
|
||||
(CanUse(RG_DINS_FIRE) ||
|
||||
(((MagicMeter && FireArrows) || LogicSpiritMapChest) && Bow && Sticks))) ||
|
||||
(((MagicMeter && FireArrows) || randoCtx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && Bow && Sticks))) ||
|
||||
(SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives &&
|
||||
CanUse(RG_STICKS)) ||
|
||||
(SmallKeys(RR_SPIRIT_TEMPLE, 3) &&
|
||||
(CanUse(RG_FIRE_ARROWS) || (LogicSpiritMapChest && Bow)) &&
|
||||
(CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && Bow)) &&
|
||||
CanUse(RG_SILVER_GAUNTLETS));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) &&
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) &&
|
||||
(CanUse(RG_DINS_FIRE) ||
|
||||
(((MagicMeter && FireArrows) || LogicSpiritSunChest) && Bow && Sticks))) ||
|
||||
(((MagicMeter && FireArrows) || randoCtx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && Bow && Sticks))) ||
|
||||
(SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives &&
|
||||
CanUse(RG_STICKS)) ||
|
||||
(SmallKeys(RR_SPIRIT_TEMPLE, 3) &&
|
||||
(CanUse(RG_FIRE_ARROWS) || (LogicSpiritSunChest && Bow)) &&
|
||||
(CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && Bow)) &&
|
||||
CanUse(RG_SILVER_GAUNTLETS));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby) && (Hookshot || HoverBoots || LogicSpiritLobbyJump);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby) && (Hookshot || HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, {[]{return (HasExplosives && Boomerang && Hookshot) ||
|
||||
(CanUse(RG_BOOMERANG) && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives) ||
|
||||
(Hookshot && CanUse(RG_SILVER_GAUNTLETS) &&
|
||||
(SmallKeys(RR_SPIRIT_TEMPLE, 3) ||
|
||||
(SmallKeys(RR_SPIRIT_TEMPLE, 2) && Boomerang && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_GS_LOBBY, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) &&
|
||||
LogicSpiritLobbyGS && Boomerang && (Hookshot || HoverBoots || LogicSpiritLobbyJump)) ||
|
||||
(LogicSpiritLobbyGS && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives && CanUse(RG_BOOMERANG)) ||
|
||||
(SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && (Hookshot || HoverBoots || LogicSpiritLobbyJump));}}),
|
||||
(SmallKeys(RR_SPIRIT_TEMPLE, 2) && Boomerang && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_GS_LOBBY, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) &&
|
||||
randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && Boomerang && (Hookshot || HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) ||
|
||||
(randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives && CanUse(RG_BOOMERANG)) ||
|
||||
(SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && (Hookshot || HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_OUTDOOR_HANDS, {[]{return CanJumpslash || HasExplosives;}}),
|
||||
@@ -114,18 +114,18 @@ void AreaTable_Init_SpiritTemple() {
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Central Locked Door", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, {[]{return (MirrorShield || (SunlightArrows && CanUse(RG_LIGHT_ARROWS))) && HasExplosives;}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, {[]{return (LogicLensSpirit || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, {[]{return (LogicLensSpirit || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, {[]{return (MirrorShield || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))) && HasExplosives;}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_SPIRIT) || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_SPIRIT) || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && (LogicSpiritWall || CanUse(RG_LONGSHOT) || HasBombchus || ((Bombs || Nuts || CanUse(RG_DINS_FIRE)) && (Bow || CanUse(RG_HOOKSHOT) || Hammer)));}}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && (randoCtx->GetTrickOption(RT_SPIRIT_WALL) || CanUse(RG_LONGSHOT) || HasBombchus || ((Bombs || Nuts || CanUse(RG_DINS_FIRE)) && (Bow || CanUse(RG_HOOKSHOT) || Hammer)));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Final Locked Door", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return CanPlay(ZeldasLullaby) && ((CanTakeDamage && LogicFlamingChests) || (Bow && Hookshot));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, {[]{return (MirrorShield && CanAdultAttack) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return CanPlay(ZeldasLullaby) && ((CanTakeDamage && randoCtx->GetTrickOption(RT_FLAMING_CHESTS)) || (Bow && Hookshot));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, {[]{return (MirrorShield && CanAdultAttack) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, {[]{return MirrorShield && HasExplosives && Hookshot;}}),
|
||||
@@ -143,7 +143,7 @@ void AreaTable_Init_SpiritTemple() {
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::SpiritTemple.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsMQ()) {
|
||||
areaTable[RR_SPIRIT_TEMPLE_MQ_LOBBY] = Area("Spirit Temple MQ Lobby", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, {[]{return true;}}),
|
||||
@@ -164,7 +164,7 @@ void AreaTable_Init_SpiritTemple() {
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return SmallKeys(RR_SPIRIT_TEMPLE, 7) && Hammer;});}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, {[]{return KokiriSword && HasBombchus && Slingshot && CanUse(RG_DINS_FIRE);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, {[]{return KokiriSword || Bombs;}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, {[]{return HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(RG_FAIRY_BOW) && CanPlay(SongOfTime)));})));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, {[]{return HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return IsAdult && (CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && CanUse(RG_FAIRY_BOW) && CanPlay(SongOfTime)));})));}}),
|
||||
//Trick: HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (SPIRIT_TEMPLE_MQ_ADULT.Adult() && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(RG_FAIRY_BOW) && CanPlay(SongOfTime)))))
|
||||
}, {
|
||||
//Exits
|
||||
@@ -175,34 +175,34 @@ void AreaTable_Init_SpiritTemple() {
|
||||
//Locations
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby) && (CanJumpslash || CanUse(RG_HOVER_BOOTS));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, {[]{return (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && (MirrorShield || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && (MirrorShield || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT, {[]{return MirrorShield && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQLowerAdult && CanUse(RG_DINS_FIRE) && Bow));}}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT, {[]{return MirrorShield && IsAdult && (CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && CanUse(RG_DINS_FIRE) && Bow));}}),
|
||||
//Trick: MirrorShield && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQLowerAdult && CanUse(RG_DINS_FIRE) && Bow))
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_SHARED, {[]{return true;}}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_BOSS_AREA, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 6) && CanPlay(ZeldasLullaby) && Hammer;}}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && CanJumpslash && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_MQ_SHARED] = Area("Spirit Temple MQ Shared", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 6);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, {[]{return (IsChild && CanUse(RG_FAIRY_SLINGSHOT) && SmallKeys(RR_SPIRIT_TEMPLE, 7)) || (IsAdult && CanUse(RG_FAIRY_BOW)) || (Bow && Slingshot);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, {[]{return CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult;}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, {[]{return CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult;}}),
|
||||
//Trick: CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, {[]{return (LogicSpiritMQSunBlockGS && Boomerang && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT)) || IsAdult;}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, {[]{return (randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && Boomerang && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT))) || IsAdult;}}),
|
||||
//Trick: (LogicSpiritMQSunBlockGS && Boomerang && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT)) || IsAdult
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && CanJumpslash && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)));}}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)));}}),
|
||||
//Trick: (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)))
|
||||
Entrance(RR_DESERT_COLOSSUS, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && CanJumpslash && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)) && IsAdult);}}),
|
||||
Entrance(RR_DESERT_COLOSSUS, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)) && IsAdult);}}),
|
||||
//Trick: (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)) && IsAdult)
|
||||
});
|
||||
|
||||
@@ -217,7 +217,7 @@ void AreaTable_Init_SpiritTemple() {
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_MQ_BOSS_AREA] = Area("Spirit Temple MQ Boss Area", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, {[]{return LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
LocationAccess(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, {[]{return MirrorShield && Hookshot;}}),
|
||||
@@ -249,8 +249,8 @@ void AreaTable_Init_SpiritTemple() {
|
||||
"Spirit Temple Boss Entryway", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, { [] { return Dungeon::SpiritTemple.IsVanilla() && false; } }),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, { [] { return Dungeon::SpiritTemple.IsMQ() && false; } }),
|
||||
Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, { [] { return randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla() && false; } }),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, { [] { return randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsMQ() && false; } }),
|
||||
Entrance(RR_SPIRIT_TEMPLE_BOSS_ROOM, { [] { return true; } }),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../../entrance.h"
|
||||
#include "../../dungeon.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_WaterTemple() {
|
||||
/*--------------------------
|
||||
@@ -12,29 +12,29 @@ void AreaTable_Init_WaterTemple() {
|
||||
---------------------------*/
|
||||
areaTable[RR_WATER_TEMPLE_ENTRYWAY] = Area("Water Temple Entryway", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return Dungeon::WaterTemple.IsVanilla();}}),
|
||||
Entrance(RR_WATER_TEMPLE_MQ_LOBBY, {[]{return Dungeon::WaterTemple.IsMQ();}}),
|
||||
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return randoCtx->GetDungeon(WATER_TEMPLE)->IsVanilla();}}),
|
||||
Entrance(RR_WATER_TEMPLE_MQ_LOBBY, {[]{return randoCtx->GetDungeon(WATER_TEMPLE)->IsMQ();}}),
|
||||
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::WaterTemple.IsVanilla()) {
|
||||
if (randoCtx->GetDungeon(WATER_TEMPLE)->IsVanilla()) {
|
||||
//Water Temple logic currently assumes that the locked door leading to the upper water raising location is unlocked from the start
|
||||
areaTable[RR_WATER_TEMPLE_LOBBY] = Area("Water Temple Lobby", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC)) && (CanUse(RG_IRON_BOOTS) || (CanUse(RG_LONGSHOT) && LogicWaterTempleTorchLongshot)));}}),
|
||||
Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}),
|
||||
Entrance(RR_WATER_TEMPLE_SOUTH_LOWER, {[]{return WaterTempleLow && HasExplosives && (CanDive || CanUse(RG_IRON_BOOTS)) && (LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC));}}),
|
||||
Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return WaterTempleLow && GoronBracelet && (IsChild || CanDive || CanUse(RG_IRON_BOOTS)) && (LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC));}}),
|
||||
Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return WaterTempleLow || ((randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC)) && (CanUse(RG_IRON_BOOTS) || (CanUse(RG_LONGSHOT) && randoCtx->GetTrickOption(RT_WATER_LONGSHOT_TORCH))));}}),
|
||||
Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return WaterTempleLow || ((randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}),
|
||||
Entrance(RR_WATER_TEMPLE_SOUTH_LOWER, {[]{return WaterTempleLow && HasExplosives && (CanDive || CanUse(RG_IRON_BOOTS)) && (randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC));}}),
|
||||
Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return WaterTempleLow && GoronBracelet && (IsChild || CanDive || CanUse(RG_IRON_BOOTS)) && (randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC));}}),
|
||||
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return WaterTempleLow && SmallKeys(RR_WATER_TEMPLE, 5);}}),
|
||||
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER, {[]{return (WaterTempleLow || WaterTempleMiddle) && (HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW));}}),
|
||||
Entrance(RR_WATER_TEMPLE_EAST_MIDDLE, {[]{return (WaterTempleLow || WaterTempleMiddle || (CanUse(RG_IRON_BOOTS) && WaterTimer >= 16)) && CanUse(RG_HOOKSHOT);}}),
|
||||
Entrance(RR_WATER_TEMPLE_WEST_MIDDLE, {[]{return WaterTempleMiddle;}}),
|
||||
Entrance(RR_WATER_TEMPLE_HIGH_WATER, {[]{return IsAdult && (CanUse(RG_HOVER_BOOTS) || (LogicDamageBoost && Bombs && CanTakeDamage));}}),
|
||||
Entrance(RR_WATER_TEMPLE_BLOCK_CORRIDOR, {[]{return (WaterTempleLow || WaterTempleMiddle) && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (CanUse(RG_LONGSHOT) || CanUse(RG_HOVER_BOOTS) || (LogicWaterCentralBow && (IsAdult || WaterTempleMiddle)));}}),
|
||||
Entrance(RR_WATER_TEMPLE_HIGH_WATER, {[]{return IsAdult && (CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_DAMAGE_BOOST) && Bombs && CanTakeDamage));}}),
|
||||
Entrance(RR_WATER_TEMPLE_BLOCK_CORRIDOR, {[]{return (WaterTempleLow || WaterTempleMiddle) && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (CanUse(RG_LONGSHOT) || CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_WATER_CENTRAL_BOW) && (IsAdult || WaterTempleMiddle)));}}),
|
||||
Entrance(RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM, {[]{return WaterTempleHigh && SmallKeys(RR_WATER_TEMPLE, 4);}}),
|
||||
Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, {[]{return WaterTempleHigh && CanUse(RG_LONGSHOT);}}),
|
||||
});
|
||||
@@ -44,9 +44,9 @@ void AreaTable_Init_WaterTemple() {
|
||||
EventAccess(&WaterTempleLow, {[]{return WaterTempleLow || CanPlay(ZeldasLullaby);}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}),
|
||||
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return WaterTempleLow || ((randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}),
|
||||
Entrance(RR_WATER_TEMPLE_MAP_ROOM, {[]{return WaterTempleHigh;}}),
|
||||
Entrance(RR_WATER_TEMPLE_CRACKED_WALL, {[]{return WaterTempleMiddle || (WaterTempleHigh && WaterTempleLow && ((CanUse(RG_HOVER_BOOTS) && LogicWaterCrackedWallHovers) || LogicWaterCrackedWallNothing));}}),
|
||||
Entrance(RR_WATER_TEMPLE_CRACKED_WALL, {[]{return WaterTempleMiddle || (WaterTempleHigh && WaterTempleLow && ((CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_WATER_CRACKED_WALL_HOVERS)) || randoCtx->GetTrickOption(RT_WATER_CRACKED_WALL)));}}),
|
||||
Entrance(RR_WATER_TEMPLE_TORCH_ROOM, {[]{return WaterTempleLow && (HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW));}}),
|
||||
});
|
||||
|
||||
@@ -77,7 +77,7 @@ void AreaTable_Init_WaterTemple() {
|
||||
areaTable[RR_WATER_TEMPLE_NORTH_LOWER] = Area("Water Temple North Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}),
|
||||
Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, {[]{return (CanUse(RG_LONGSHOT) || (LogicWaterBossKeyRegion && CanUse(RG_HOVER_BOOTS))) && SmallKeys(RR_WATER_TEMPLE, 4);}}),
|
||||
Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, {[]{return (CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_WATER_BK_REGION) && CanUse(RG_HOVER_BOOTS))) && SmallKeys(RR_WATER_TEMPLE, 4);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_BOULDERS_LOWER] = Area("Water Temple Boulders Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -87,7 +87,7 @@ void AreaTable_Init_WaterTemple() {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return SmallKeys(RR_WATER_TEMPLE, 4);}}),
|
||||
Entrance(RR_WATER_TEMPLE_BLOCK_ROOM, {[]{return true;}}),
|
||||
Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (IsAdult && (CanUse(RG_HOVER_BOOTS) || LogicWaterNorthBasementLedgeJump)) || (CanUse(RG_HOVER_BOOTS) && CanUse(RG_IRON_BOOTS));}}),
|
||||
Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (IsAdult && (CanUse(RG_HOVER_BOOTS) || randoCtx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP))) || (CanUse(RG_HOVER_BOOTS) && CanUse(RG_IRON_BOOTS));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_BLOCK_ROOM] = Area("Water Temple Block Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
@@ -106,7 +106,7 @@ void AreaTable_Init_WaterTemple() {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, {[]{return true;}}),
|
||||
Entrance(RR_WATER_TEMPLE_JETS_ROOM, {[]{return IsAdult;}}),
|
||||
Entrance(RR_WATER_TEMPLE_BOSS_KEY_ROOM, {[]{return (CanUse(RG_IRON_BOOTS) || (IsAdult && LogicWaterBKJumpDive)) && SmallKeys(RR_WATER_TEMPLE, 5);}}),
|
||||
Entrance(RR_WATER_TEMPLE_BOSS_KEY_ROOM, {[]{return (CanUse(RG_IRON_BOOTS) || (IsAdult && randoCtx->GetTrickOption(RT_WATER_BK_JUMP_DIVE))) && SmallKeys(RR_WATER_TEMPLE, 5);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_BOSS_KEY_ROOM] = Area("Water Temple Boss Key Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
@@ -117,7 +117,7 @@ void AreaTable_Init_WaterTemple() {
|
||||
LocationAccess(RC_WATER_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (CanUse(RG_IRON_BOOTS) || (IsAdult && LogicWaterBKJumpDive) || IsChild || CanDive) && SmallKeys(RR_WATER_TEMPLE, 5);}}),
|
||||
Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (CanUse(RG_IRON_BOOTS) || (IsAdult && randoCtx->GetTrickOption(RT_WATER_BK_JUMP_DIVE)) || IsChild || CanDive) && SmallKeys(RR_WATER_TEMPLE, 5);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_SOUTH_LOWER] = Area("Water Temple South Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -136,8 +136,8 @@ void AreaTable_Init_WaterTemple() {
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_DRAGON_ROOM] = Area("Water Temple Dragon Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_WATER_TEMPLE_DRAGON_CHEST, {[]{return (CanUse(RG_HOOKSHOT) && CanUse(RG_IRON_BOOTS)) || (((IsAdult && LogicWaterDragonAdult && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || HasBombchus)) || (IsChild && LogicWaterDragonChild && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasBombchus))) && (CanDive || CanUse(RG_IRON_BOOTS))) ||
|
||||
Here(RR_WATER_TEMPLE_RIVER, []{return IsAdult && CanUse(RG_FAIRY_BOW) && ((LogicWaterDragonAdult && (CanDive || CanUse(RG_IRON_BOOTS))) || LogicWaterDragonJumpDive);});}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_DRAGON_CHEST, {[]{return (CanUse(RG_HOOKSHOT) && CanUse(RG_IRON_BOOTS)) || (((IsAdult && randoCtx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || HasBombchus)) || (IsChild && randoCtx->GetTrickOption(RT_WATER_CHILD_DRAGON) && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasBombchus))) && (CanDive || CanUse(RG_IRON_BOOTS))) ||
|
||||
Here(RR_WATER_TEMPLE_RIVER, []{return IsAdult && CanUse(RG_FAIRY_BOW) && ((randoCtx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (CanDive || CanUse(RG_IRON_BOOTS))) || randoCtx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE));});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return true;}}),
|
||||
@@ -155,7 +155,7 @@ void AreaTable_Init_WaterTemple() {
|
||||
EventAccess(&WaterTempleMiddle, {[]{return WaterTempleMiddle || CanPlay(ZeldasLullaby);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, {[]{return CanUse(RG_LONGSHOT) || (((LogicWaterCentralGSFW && CanUse(RG_FARORES_WIND) && (CanUse(RG_FAIRY_BOW) || CanUse(RG_DINS_FIRE) || SmallKeys(RR_WATER_TEMPLE, 5))) || (LogicWaterCentralGSIrons && CanUse(RG_IRON_BOOTS) && ((CanUse(RG_HOOKSHOT) && CanUse(RG_FAIRY_BOW)) || (CanUse(RG_DINS_FIRE))))) && WaterTempleHigh && HookshotOrBoomerang);}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, {[]{return CanUse(RG_LONGSHOT) || (((randoCtx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && CanUse(RG_FARORES_WIND) && (CanUse(RG_FAIRY_BOW) || CanUse(RG_DINS_FIRE) || SmallKeys(RR_WATER_TEMPLE, 5))) || (randoCtx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && CanUse(RG_IRON_BOOTS) && ((CanUse(RG_HOOKSHOT) && CanUse(RG_FAIRY_BOW)) || (CanUse(RG_DINS_FIRE))))) && WaterTempleHigh && HookshotOrBoomerang);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}),
|
||||
@@ -202,7 +202,7 @@ void AreaTable_Init_WaterTemple() {
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM] = Area("Water Temple Falling Platform Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, {[]{return CanUse(RG_LONGSHOT) || (LogicWaterFallingPlatformGSBoomerang && IsChild && CanUse(RG_BOOMERANG)) || (LogicWaterFallingPlatformGSHookshot && IsAdult && CanUse(RG_HOOKSHOT));}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, {[]{return CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_WATER_RANG_FALLING_PLATFORM_GS) && IsChild && CanUse(RG_BOOMERANG)) || (randoCtx->GetTrickOption(RT_WATER_HOOKSHOT_FALLING_PLATFORM_GS) && IsAdult && CanUse(RG_HOOKSHOT));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return CanUse(RG_HOOKSHOT) && SmallKeys(RR_WATER_TEMPLE, 4);}}),
|
||||
@@ -233,7 +233,7 @@ void AreaTable_Init_WaterTemple() {
|
||||
areaTable[RR_WATER_TEMPLE_RIVER] = Area("Water Temple River", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_WATER_TEMPLE_RIVER_CHEST, {[]{return (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (IsAdult || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_GS_RIVER, {[]{return (CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT)) || (LogicWaterRiverGS && CanUse(RG_LONGSHOT));}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_GS_RIVER, {[]{return (CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_WATER_RIVER_GS) && CanUse(RG_LONGSHOT));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_DRAGON_ROOM, {[]{return (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (IsAdult || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
|
||||
@@ -252,7 +252,7 @@ void AreaTable_Init_WaterTemple() {
|
||||
/*---------------------------
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::WaterTemple.IsMQ()) {
|
||||
if (randoCtx->GetDungeon(WATER_TEMPLE)->IsMQ()) {
|
||||
areaTable[RR_WATER_TEMPLE_MQ_LOBBY] = Area("Water Temple MQ Lobby", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
@@ -264,7 +264,7 @@ void AreaTable_Init_WaterTemple() {
|
||||
areaTable[RR_WATER_TEMPLE_MQ_DIVE] = Area("Water Temple MQ Dive", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_MAP_CHEST, {[]{return HasFireSource && IsAdult && CanUse(RG_HOOKSHOT);}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, {[]{return IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanPlay(SongOfTime)));}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, {[]{return IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((randoCtx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanPlay(SongOfTime)));}}),
|
||||
//Trick: IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanPlay(SongOfTime)))
|
||||
}, {
|
||||
//Exits
|
||||
@@ -286,7 +286,7 @@ void AreaTable_Init_WaterTemple() {
|
||||
EventAccess(&NutPot, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return IsAdult && WaterTimer >= 24 && CanUse(RG_DINS_FIRE) && (LogicWaterDragonJumpDive || CanDive || CanUse(RG_IRON_BOOTS));}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return IsAdult && WaterTimer >= 24 && CanUse(RG_DINS_FIRE) && (randoCtx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE) || CanDive || CanUse(RG_IRON_BOOTS));}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_GS_RIVER, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
@@ -295,9 +295,9 @@ void AreaTable_Init_WaterTemple() {
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS] = Area("Water Temple MQ Basement Gated Areas", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, {[]{return HoverBoots || CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump;}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, {[]{return HoverBoots || CanUse(RG_SCARECROW) || randoCtx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP);}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, {[]{return CanUse(RG_FIRE_ARROWS) && (HoverBoots || CanUse(RG_SCARECROW));}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, {[]{return LogicWaterMQLockedGS || (SmallKeys(RR_WATER_TEMPLE, 2) && (HoverBoots || CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump) && CanJumpslash);}}),
|
||||
LocationAccess(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, {[]{return randoCtx->GetTrickOption(RT_WATER_MQ_LOCKED_GS) || (SmallKeys(RR_WATER_TEMPLE, 2) && (HoverBoots || CanUse(RG_SCARECROW) || randoCtx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP)) && CanJumpslash);}}),
|
||||
//Trick: LogicWaterMQLockedGS || (SmallKeys(RR_WATER_TEMPLE, 2) && (HoverBoots || CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump))
|
||||
}, {});
|
||||
}
|
||||
@@ -309,8 +309,8 @@ void AreaTable_Init_WaterTemple() {
|
||||
Area("Water Temple Boss Entryway", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, { [] { return Dungeon::WaterTemple.IsVanilla() && false; } }),
|
||||
Entrance(RR_WATER_TEMPLE_MQ_LOBBY, { [] { return Dungeon::WaterTemple.IsMQ() && false; } }),
|
||||
Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, { [] { return randoCtx->GetDungeon(WATER_TEMPLE)->IsVanilla() && false; } }),
|
||||
Entrance(RR_WATER_TEMPLE_MQ_LOBBY, { [] { return randoCtx->GetDungeon(WATER_TEMPLE)->IsMQ() && false; } }),
|
||||
Entrance(RR_WATER_TEMPLE_BOSS_ROOM, { [] { return true; } }),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../../entrance.h"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Rando;
|
||||
|
||||
void AreaTable_Init_ZorasDomain() {
|
||||
areaTable[RR_ZR_FRONT] = Area("ZR Front", "Zora River", RHT_ZORAS_RIVER, DAY_NIGHT_CYCLE, {}, {
|
||||
@@ -31,8 +31,8 @@ void AreaTable_Init_ZorasDomain() {
|
||||
LocationAccess(RC_ZR_FROGS_SARIAS_SONG, {[]{return IsChild && CanPlay(SariasSong);}}),
|
||||
LocationAccess(RC_ZR_FROGS_SUNS_SONG, {[]{return IsChild && CanPlay(SunsSong);}}),
|
||||
LocationAccess(RC_ZR_FROGS_SONG_OF_TIME, {[]{return IsChild && CanPlay(SongOfTime);}}),
|
||||
LocationAccess(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && LogicZoraRiverLower);}}),
|
||||
LocationAccess(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && LogicZoraRiverUpper);}}),
|
||||
LocationAccess(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && randoCtx->GetTrickOption(RT_ZR_LOWER));}}),
|
||||
LocationAccess(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && randoCtx->GetTrickOption(RT_ZR_UPPER));}}),
|
||||
LocationAccess(RC_ZR_GS_LADDER, {[]{return IsChild && AtNight && CanChildAttack && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_ZR_GS_NEAR_RAISED_GROTTOS, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_ZR_GS_ABOVE_BRIDGE, {[]{return IsAdult && CanUse(RG_HOOKSHOT) && AtNight && CanGetNightTimeGS;}}),
|
||||
@@ -45,7 +45,7 @@ void AreaTable_Init_ZorasDomain() {
|
||||
Entrance(RR_ZR_FAIRY_GROTTO, {[]{return Here(RR_ZORAS_RIVER, []{return CanBlastOrSmash;});}}),
|
||||
Entrance(RR_THE_LOST_WOODS, {[]{return CanDive || CanUse(RG_IRON_BOOTS);}}),
|
||||
Entrance(RR_ZR_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
|
||||
Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return CanPlay(ZeldasLullaby) || (IsChild && LogicZoraWithCucco) || (IsAdult && CanUse(RG_HOVER_BOOTS) && LogicZoraWithHovers);}}),
|
||||
Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return CanPlay(ZeldasLullaby) || (IsChild && randoCtx->GetTrickOption(RT_ZR_CUCCO)) || (IsAdult && CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_ZR_HOVERS));}}),
|
||||
});
|
||||
|
||||
areaTable[RR_ZR_BEHIND_WATERFALL] = Area("ZR Behind Waterfall", "Zora River", RHT_ZORAS_RIVER, DAY_NIGHT_CYCLE, {}, {}, {
|
||||
@@ -88,27 +88,27 @@ void AreaTable_Init_ZorasDomain() {
|
||||
EventAccess(&StickPot, {[]{return StickPot || IsChild;}}),
|
||||
EventAccess(&FishGroup, {[]{return FishGroup || IsChild;}}),
|
||||
EventAccess(&KingZoraThawed, {[]{return KingZoraThawed || (IsAdult && BlueFire);}}),
|
||||
EventAccess(&DeliverLetter, {[]{return DeliverLetter || (RutosLetter && IsChild && ZorasFountain.IsNot(ZORASFOUNTAIN_OPEN));}}),
|
||||
EventAccess(&DeliverLetter, {[]{return DeliverLetter || (RutosLetter && IsChild && randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).IsNot(RO_ZF_OPEN));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_ZD_DIVING_MINIGAME, {[]{return IsChild;}}),
|
||||
LocationAccess(RC_ZD_CHEST, {[]{return IsChild && CanUse(RG_STICKS);}}),
|
||||
LocationAccess(RC_ZD_KING_ZORA_THAWED, {[]{return KingZoraThawed;}}),
|
||||
LocationAccess(RC_ZD_TRADE_PRESCRIPTION, {[]{return KingZoraThawed && Prescription;}}),
|
||||
LocationAccess(RC_ZD_GS_FROZEN_WATERFALL, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || CanUse(RG_FAIRY_SLINGSHOT) || Bow || (MagicMeter && (CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD))) || (LogicDomainGS && CanJumpslash)) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_ZD_GS_FROZEN_WATERFALL, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || CanUse(RG_FAIRY_SLINGSHOT) || Bow || (MagicMeter && (CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD))) || (randoCtx->GetTrickOption(RT_ZD_GS) && CanJumpslash)) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(RC_ZD_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return true;}}),
|
||||
Entrance(RR_LAKE_HYLIA, {[]{return IsChild && (CanDive || CanUse(RG_IRON_BOOTS));}}),
|
||||
Entrance(RR_ZD_BEHIND_KING_ZORA, {[]{return DeliverLetter || ZorasFountain.Is(ZORASFOUNTAIN_OPEN) || (ZorasFountain.Is(ZORASFOUNTAIN_ADULT) && IsAdult) || (LogicKingZoraSkip && IsAdult);}}),
|
||||
Entrance(RR_ZD_BEHIND_KING_ZORA, {[]{return DeliverLetter || randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN) || (randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_CLOSED_CHILD) && IsAdult) || (randoCtx->GetTrickOption(RT_ZD_KING_ZORA_SKIP) && IsAdult);}}),
|
||||
Entrance(RR_ZD_SHOP, {[]{return IsChild || BlueFire;}}),
|
||||
Entrance(RR_ZD_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
|
||||
});
|
||||
|
||||
areaTable[RR_ZD_BEHIND_KING_ZORA] = Area("ZD Behind King Zora", "Zoras Domain", RHT_ZORAS_DOMAIN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_ZORAS_DOMAIN, {[]{return DeliverLetter || ZorasFountain.Is(ZORASFOUNTAIN_OPEN) || (ZorasFountain.Is(ZORASFOUNTAIN_ADULT) && IsAdult);}}),
|
||||
Entrance(RR_ZORAS_DOMAIN, {[]{return DeliverLetter || randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN) || (randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_CLOSED_CHILD) && IsAdult);}}),
|
||||
Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}),
|
||||
});
|
||||
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "settings.hpp"
|
||||
#include "dungeon.hpp"
|
||||
|
||||
using namespace Settings;
|
||||
#include "../dungeon.h"
|
||||
#include "../context.h"
|
||||
|
||||
namespace Logic {
|
||||
|
||||
@@ -440,29 +438,30 @@ namespace Logic {
|
||||
|
||||
switch (itemName) {
|
||||
// Adult items
|
||||
case RG_FAIRY_BOW: return IsAdult || BowAsChild;
|
||||
case RG_MEGATON_HAMMER: return IsAdult || HammerAsChild;
|
||||
case RG_IRON_BOOTS: return IsAdult || IronBootsAsChild;
|
||||
case RG_HOVER_BOOTS: return IsAdult || HoverBootsAsChild;
|
||||
case RG_HOOKSHOT: return IsAdult || HookshotAsChild;
|
||||
case RG_LONGSHOT: return IsAdult || HookshotAsChild;
|
||||
// TODO: Uncomment those if we ever implement more item usability settings
|
||||
case RG_FAIRY_BOW: return IsAdult;// || BowAsChild;
|
||||
case RG_MEGATON_HAMMER: return IsAdult;// || HammerAsChild;
|
||||
case RG_IRON_BOOTS: return IsAdult;// || IronBootsAsChild;
|
||||
case RG_HOVER_BOOTS: return IsAdult;// || HoverBootsAsChild;
|
||||
case RG_HOOKSHOT: return IsAdult;// || HookshotAsChild;
|
||||
case RG_LONGSHOT: return IsAdult;// || HookshotAsChild;
|
||||
case RG_SILVER_GAUNTLETS: return IsAdult;
|
||||
case RG_GOLDEN_GAUNTLETS: return IsAdult;
|
||||
case RG_GORON_TUNIC: return IsAdult || GoronTunicAsChild;
|
||||
case RG_ZORA_TUNIC: return IsAdult || ZoraTunicAsChild;
|
||||
case RG_SCARECROW: return IsAdult || HookshotAsChild;
|
||||
case RG_DISTANT_SCARECROW: return IsAdult || HookshotAsChild;
|
||||
case RG_GORON_TUNIC: return IsAdult;// || GoronTunicAsChild;
|
||||
case RG_ZORA_TUNIC: return IsAdult;// || ZoraTunicAsChild;
|
||||
case RG_SCARECROW: return IsAdult;// || HookshotAsChild;
|
||||
case RG_DISTANT_SCARECROW: return IsAdult;// || HookshotAsChild;
|
||||
case RG_HYLIAN_SHIELD: return IsAdult;
|
||||
case RG_MIRROR_SHIELD: return IsAdult || MirrorShieldAsChild;
|
||||
case RG_MASTER_SWORD: return IsAdult || MasterSwordAsChild;
|
||||
case RG_BIGGORON_SWORD: return IsAdult || BiggoronSwordAsChild;
|
||||
case RG_MIRROR_SHIELD: return IsAdult;// || MirrorShieldAsChild;
|
||||
case RG_MASTER_SWORD: return IsAdult;// || MasterSwordAsChild;
|
||||
case RG_BIGGORON_SWORD: return IsAdult;// || BiggoronSwordAsChild;
|
||||
|
||||
// Child items
|
||||
case RG_FAIRY_SLINGSHOT: return IsChild || SlingshotAsAdult;
|
||||
case RG_BOOMERANG: return IsChild || BoomerangAsAdult;
|
||||
case RG_KOKIRI_SWORD: return IsChild || KokiriSwordAsAdult;
|
||||
case RG_STICKS: return IsChild || StickAsAdult;
|
||||
case RG_DEKU_SHIELD: return IsChild || DekuShieldAsAdult;
|
||||
case RG_FAIRY_SLINGSHOT: return IsChild;// || SlingshotAsAdult;
|
||||
case RG_BOOMERANG: return IsChild;// || BoomerangAsAdult;
|
||||
case RG_KOKIRI_SWORD: return IsChild;// || KokiriSwordAsAdult;
|
||||
case RG_STICKS: return IsChild;// || StickAsAdult;
|
||||
case RG_DEKU_SHIELD: return IsChild;// || DekuShieldAsAdult;
|
||||
|
||||
// Magic items
|
||||
default: return MagicMeter && (IsMagicItem(itemName) || (IsMagicArrow(itemName) && CanUse(RG_FAIRY_BOW)));
|
||||
@@ -505,7 +504,7 @@ namespace Logic {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t GetDifficultyValueFromString(Option& glitchOption) {
|
||||
uint8_t GetDifficultyValueFromString(Rando::Option& glitchOption) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -522,11 +521,12 @@ namespace Logic {
|
||||
}
|
||||
|
||||
bool CanDoGlitch(GlitchType glitch) {
|
||||
// TODO: Uncomment when glitches are implemented
|
||||
switch(glitch) {
|
||||
case GlitchType::EquipSwapDins:
|
||||
return ((IsAdult && HasItem(RG_DINS_FIRE)) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_DINS_FIRE)))) && GlitchEquipSwapDins;
|
||||
return ((IsAdult && HasItem(RG_DINS_FIRE)) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_DINS_FIRE)))) && false;//GlitchEquipSwapDins;
|
||||
case GlitchType::EquipSwap: // todo: add bunny hood to adult item equippable list and child trade item to child item equippable list
|
||||
return ((IsAdult && (HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE))) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_FAIRY_SLINGSHOT) || HasItem(RG_BOOMERANG) || HasBottle || Nuts || Ocarina || HasItem(RG_LENS_OF_TRUTH) || HasExplosives || (MagicBean || MagicBeanPack) || HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE)))) && GlitchEquipSwap;
|
||||
return ((IsAdult && (HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE))) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_FAIRY_SLINGSHOT) || HasItem(RG_BOOMERANG) || HasBottle || Nuts || Ocarina || HasItem(RG_LENS_OF_TRUTH) || HasExplosives || (MagicBean || MagicBeanPack) || HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE)))) && false;//GlitchEquipSwap;
|
||||
}
|
||||
|
||||
//Shouldn't be reached
|
||||
@@ -535,6 +535,7 @@ namespace Logic {
|
||||
|
||||
//Updates all logic helpers. Should be called whenever a non-helper is changed
|
||||
void UpdateHelpers() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
NumBottles = ((NoBottles) ? 0 : (Bottles + ((DeliverLetter) ? 1 : 0)));
|
||||
HasBottle = NumBottles >= 1;
|
||||
Slingshot = (ProgressiveBulletBag >= 1) && (BuySeed || AmmoCanDrop);
|
||||
@@ -553,7 +554,7 @@ namespace Logic {
|
||||
AdultsWallet = ProgressiveWallet >= 1;
|
||||
BiggoronSword = BiggoronSword || ProgressiveGiantKnife >= 2;
|
||||
|
||||
ScarecrowSong = ScarecrowSong || FreeScarecrow || (ChildScarecrow && AdultScarecrow);
|
||||
ScarecrowSong = ScarecrowSong || ctx->GetOption(RSK_SKIP_SCARECROWS_SONG) || (ChildScarecrow && AdultScarecrow);
|
||||
Scarecrow = Hookshot && CanPlay(ScarecrowSong);
|
||||
DistantScarecrow = Longshot && CanPlay(ScarecrowSong);
|
||||
|
||||
@@ -570,28 +571,29 @@ namespace Logic {
|
||||
Nuts = DekuNutDrop || Nuts;
|
||||
Sticks = DekuStickDrop || Sticks;
|
||||
Bugs = HasBottle && BugsAccess;
|
||||
BlueFire = (HasBottle && BlueFireAccess) || (BlueFireArrows && CanUse(RG_ICE_ARROWS));
|
||||
BlueFire = (HasBottle && BlueFireAccess) || (ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && CanUse(RG_ICE_ARROWS));
|
||||
Fish = HasBottle && FishAccess;
|
||||
Fairy = HasBottle && FairyAccess;
|
||||
|
||||
FoundBombchus = (BombchuDrop || Bombchus || Bombchus5 || Bombchus10 || Bombchus20);
|
||||
CanPlayBowling = (BombchusInLogic && FoundBombchus) || (!BombchusInLogic && BombBag);
|
||||
HasBombchus = (BuyBombchus10 || BuyBombchus20 || (AmmoDrops.Is(AMMODROPS_BOMBCHU) && FoundBombchus));
|
||||
CanPlayBowling = (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && FoundBombchus) || (!ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && BombBag);
|
||||
// TODO: Implement Ammo Drop Setting in place of bombchu drops
|
||||
HasBombchus = (BuyBombchus10 || BuyBombchus20 || (ctx->GetOption(RSK_ENABLE_BOMBCHU_DROPS).Is(RO_AMMO_DROPS_ON_PLUS_BOMBCHU) && FoundBombchus));
|
||||
|
||||
HasExplosives = Bombs || (BombchusInLogic && HasBombchus);
|
||||
HasExplosives = Bombs || (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && HasBombchus);
|
||||
|
||||
HasBoots = IronBoots || HoverBoots;
|
||||
|
||||
//Unshuffled adult trade quest
|
||||
Eyedrops = Eyedrops || (!ShuffleAdultTradeQuest && ClaimCheck);
|
||||
EyeballFrog = EyeballFrog || (!ShuffleAdultTradeQuest && Eyedrops);
|
||||
Prescription = Prescription || (!ShuffleAdultTradeQuest && EyeballFrog);
|
||||
BrokenSword = BrokenSword || (!ShuffleAdultTradeQuest && Prescription);
|
||||
PoachersSaw = PoachersSaw || (!ShuffleAdultTradeQuest && BrokenSword);
|
||||
OddPoultice = OddPoultice || (!ShuffleAdultTradeQuest && PoachersSaw);
|
||||
OddMushroom = OddMushroom || (!ShuffleAdultTradeQuest && OddPoultice);
|
||||
Cojiro = Cojiro || (!ShuffleAdultTradeQuest && OddMushroom);
|
||||
PocketEgg = PocketEgg || (!ShuffleAdultTradeQuest && Cojiro);
|
||||
Eyedrops = Eyedrops || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && ClaimCheck);
|
||||
EyeballFrog = EyeballFrog || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Eyedrops);
|
||||
Prescription = Prescription || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && EyeballFrog);
|
||||
BrokenSword = BrokenSword || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Prescription);
|
||||
PoachersSaw = PoachersSaw || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && BrokenSword);
|
||||
OddPoultice = OddPoultice || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && PoachersSaw);
|
||||
OddMushroom = OddMushroom || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && OddPoultice);
|
||||
Cojiro = Cojiro || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && OddMushroom);
|
||||
PocketEgg = PocketEgg || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Cojiro);
|
||||
|
||||
// IsChild = Age == AGE_CHILD;
|
||||
// IsAdult = Age == AGE_ADULT;
|
||||
@@ -604,34 +606,34 @@ namespace Logic {
|
||||
CanStunDeku = CanAdultAttack || CanChildAttack || Nuts || HasShield;
|
||||
CanCutShrubs = CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BOOMERANG) || HasExplosives || CanUse(RG_MASTER_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_BIGGORON_SWORD);
|
||||
CanDive = ProgressiveScale >= 1;
|
||||
CanLeaveForest = OpenForest.IsNot(OPENFOREST_CLOSED) || IsAdult || DekuTreeClear || ShuffleInteriorEntrances || ShuffleOverworldEntrances;
|
||||
CanLeaveForest = ctx->GetOption(RSK_FOREST).IsNot(RO_FOREST_CLOSED) || IsAdult || DekuTreeClear || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES);
|
||||
CanPlantBugs = IsChild && Bugs;
|
||||
CanRideEpona = IsAdult && Epona && CanPlay(EponasSong);
|
||||
CanSummonGossipFairy = Ocarina && (ZeldasLullaby || EponasSong || SongOfTime || SunsSong);
|
||||
CanSummonGossipFairyWithoutSuns = Ocarina && (ZeldasLullaby || EponasSong || SongOfTime);
|
||||
Hearts = BaseHearts + HeartContainer + (PieceOfHeart >> 2);
|
||||
EffectiveHealth = ((Hearts << (2 + DoubleDefense)) >> Multiplier) + ((Hearts << (2 + DoubleDefense)) % (1 << Multiplier) > 0); //Number of half heart hits to die, ranges from 1 to 160
|
||||
FireTimer = CanUse(RG_GORON_TUNIC) ? 255 : (LogicFewerTunicRequirements) ? (Hearts * 8) : 0;
|
||||
WaterTimer = CanUse(RG_ZORA_TUNIC) ? 255 : (LogicFewerTunicRequirements) ? (Hearts * 8) : 0;
|
||||
FireTimer = CanUse(RG_GORON_TUNIC) ? 255 : (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS)) ? (Hearts * 8) : 0;
|
||||
WaterTimer = CanUse(RG_ZORA_TUNIC) ? 255 : (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS)) ? (Hearts * 8) : 0;
|
||||
NeedNayrusLove = (EffectiveHealth == 1);
|
||||
CanSurviveDamage = !NeedNayrusLove || CanUse(RG_NAYRUS_LOVE);
|
||||
CanTakeDamage = Fairy || CanSurviveDamage;
|
||||
CanTakeDamageTwice = (Fairy && NumBottles >= 2) || ((EffectiveHealth == 2) && (CanUse(RG_NAYRUS_LOVE) || Fairy)) || (EffectiveHealth > 2);
|
||||
//CanPlantBean = IsChild && (MagicBean || MagicBeanPack);
|
||||
CanOpenBombGrotto = CanBlastOrSmash && (ShardOfAgony || LogicGrottosWithoutAgony);
|
||||
CanOpenStormGrotto = CanPlay(SongOfStorms) && (ShardOfAgony || LogicGrottosWithoutAgony);
|
||||
CanOpenBombGrotto = CanBlastOrSmash && (ShardOfAgony || ctx->GetTrickOption(RT_GROTTOS_WITHOUT_AGONY));
|
||||
CanOpenStormGrotto = CanPlay(SongOfStorms) && (ShardOfAgony || ctx->GetTrickOption(RT_GROTTOS_WITHOUT_AGONY));
|
||||
HookshotOrBoomerang = CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG);
|
||||
CanGetNightTimeGS = (CanPlay(SunsSong) || !NightGSExpectSuns);
|
||||
CanGetNightTimeGS = (CanPlay(SunsSong) || !ctx->GetOption(RSK_SKULLS_SUNS_SONG));
|
||||
|
||||
GuaranteeTradePath = ShuffleInteriorEntrances || ShuffleOverworldEntrances || LogicBiggoronBolero || CanBlastOrSmash || StopGCRollingGoronAsAdult;
|
||||
GuaranteeTradePath = ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetTrickOption(RT_DMT_BOLERO_BIGGORON) || CanBlastOrSmash || StopGCRollingGoronAsAdult;
|
||||
//GuaranteeHint = (hints == "Mask" && MaskofTruth) || (hints == "Agony") || (hints != "Mask" && hints != "Agony");
|
||||
HasFireSource = CanUse(RG_DINS_FIRE) || CanUse(RG_FIRE_ARROWS);
|
||||
HasFireSourceWithTorch = HasFireSource || CanUse(RG_STICKS);
|
||||
|
||||
//Gerudo Fortress
|
||||
CanFinishGerudoFortress = (GerudoFortress.Is(GERUDOFORTRESS_NORMAL) && GerudoFortressKeys >= 4 && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || LogicGerudoKitchen)) ||
|
||||
(GerudoFortress.Is(GERUDOFORTRESS_FAST) && GerudoFortressKeys >= 1 && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))) ||
|
||||
(GerudoFortress.IsNot(GERUDOFORTRESS_NORMAL) && GerudoFortress.IsNot(GERUDOFORTRESS_FAST));
|
||||
CanFinishGerudoFortress = (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_NORMAL) && GerudoFortressKeys >= 4 && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_GF_KITCHEN))) ||
|
||||
(ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_FAST) && GerudoFortressKeys >= 1 && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))) ||
|
||||
(ctx->GetOption(RSK_GERUDO_FORTRESS).IsNot(RO_GF_NORMAL) && ctx->GetOption(RSK_GERUDO_FORTRESS).IsNot(RO_GF_FAST));
|
||||
|
||||
HasShield = CanUse(RG_HYLIAN_SHIELD) || CanUse(RG_DEKU_SHIELD); //Mirror shield can't reflect attacks
|
||||
CanShield = CanUse(RG_MIRROR_SHIELD) || HasShield;
|
||||
@@ -649,26 +651,25 @@ namespace Logic {
|
||||
DungeonCount = (DekuTreeClear ? 1:0) + (DodongosCavernClear ? 1:0) + (JabuJabusBellyClear ? 1:0) + (ForestTempleClear ? 1:0) + (FireTempleClear ? 1:0) + (WaterTempleClear ? 1:0) + (SpiritTempleClear ? 1:0) + (ShadowTempleClear ? 1:0);
|
||||
HasAllStones = StoneCount == 3;
|
||||
HasAllMedallions = MedallionCount == 6;
|
||||
GregInBridgeLogic = BridgeRewardOptions.Is(BRIDGE_OPTION_GREG);
|
||||
GregInLacsLogic = LACSRewardOptions.Is(LACS_OPTION_GREG);
|
||||
GregInBridgeLogic = ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG);
|
||||
GregInLacsLogic = ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD);
|
||||
|
||||
CanBuildRainbowBridge = Bridge.Is(RAINBOWBRIDGE_OPEN) ||
|
||||
(Bridge.Is(RAINBOWBRIDGE_VANILLA) && ShadowMedallion && SpiritMedallion && LightArrows) ||
|
||||
(Bridge.Is(RAINBOWBRIDGE_STONES) && StoneCount + (Greg && GregInBridgeLogic ? 1 : 0) >= BridgeStoneCount.Value<uint8_t>()) ||
|
||||
(Bridge.Is(RAINBOWBRIDGE_MEDALLIONS) && MedallionCount + (Greg && GregInBridgeLogic ? 1 : 0) >= BridgeMedallionCount.Value<uint8_t>()) ||
|
||||
(Bridge.Is(RAINBOWBRIDGE_REWARDS) && StoneCount + MedallionCount + (Greg && GregInBridgeLogic ? 1 : 0) >= BridgeRewardCount.Value<uint8_t>()) ||
|
||||
(Bridge.Is(RAINBOWBRIDGE_DUNGEONS) && DungeonCount + (Greg && GregInBridgeLogic ? 1 : 0) >= BridgeDungeonCount.Value<uint8_t>()) ||
|
||||
(Bridge.Is(RAINBOWBRIDGE_TOKENS) && GoldSkulltulaTokens >= BridgeTokenCount.Value<uint8_t>()) ||
|
||||
(Bridge.Is(RAINBOWBRIDGE_GREG) && Greg);
|
||||
|
||||
CanTriggerLACS = (LACSCondition == LACSCONDITION_VANILLA && ShadowMedallion && SpiritMedallion) ||
|
||||
(LACSCondition == LACSCONDITION_STONES && StoneCount + (Greg && GregInLacsLogic ? 1 : 0) >= LACSStoneCount.Value<uint8_t>()) ||
|
||||
(LACSCondition == LACSCONDITION_MEDALLIONS && MedallionCount + (Greg && GregInLacsLogic ? 1 : 0) >= LACSMedallionCount.Value<uint8_t>()) ||
|
||||
(LACSCondition == LACSCONDITION_REWARDS && StoneCount + MedallionCount + (Greg && GregInLacsLogic ? 1 : 0) >= LACSRewardCount.Value<uint8_t>()) ||
|
||||
(LACSCondition == LACSCONDITION_DUNGEONS && DungeonCount + (Greg && GregInLacsLogic ? 1 : 0) >= LACSDungeonCount.Value<uint8_t>()) ||
|
||||
(LACSCondition == LACSCONDITION_TOKENS && GoldSkulltulaTokens >= LACSTokenCount.Value<uint8_t>());
|
||||
CanCompleteTriforce = TriforcePieces >= TriforceHuntRequired.Value<uint8_t>();
|
||||
CanBuildRainbowBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN) ||
|
||||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA) && ShadowMedallion && SpiritMedallion && LightArrows) ||
|
||||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES) && StoneCount + (Greg && GregInBridgeLogic ? 1 : 0) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Value<uint8_t>()) ||
|
||||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS) && MedallionCount + (Greg && GregInBridgeLogic ? 1 : 0) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Value<uint8_t>()) ||
|
||||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS) && StoneCount + MedallionCount + (Greg && GregInBridgeLogic ? 1 : 0) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value<uint8_t>()) ||
|
||||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && DungeonCount + (Greg && GregInBridgeLogic ? 1 : 0) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value<uint8_t>()) ||
|
||||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) && GoldSkulltulaTokens >= ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value<uint8_t>()) ||
|
||||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG) && Greg);
|
||||
|
||||
CanTriggerLACS = (ctx->GetSettings()->LACSCondition() == RO_LACS_VANILLA && ShadowMedallion && SpiritMedallion) ||
|
||||
(ctx->GetSettings()->LACSCondition() == RO_LACS_STONES && StoneCount + (Greg && GregInLacsLogic ? 1 : 0) >= ctx->GetOption(RSK_LACS_STONE_COUNT).Value<uint8_t>()) ||
|
||||
(ctx->GetSettings()->LACSCondition() == RO_LACS_MEDALLIONS && MedallionCount + (Greg && GregInLacsLogic ? 1 : 0) >= ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Value<uint8_t>()) ||
|
||||
(ctx->GetSettings()->LACSCondition() == RO_LACS_REWARDS && StoneCount + MedallionCount + (Greg && GregInLacsLogic ? 1 : 0) >= ctx->GetOption(RSK_LACS_REWARD_COUNT).Value<uint8_t>()) ||
|
||||
(ctx->GetSettings()->LACSCondition() == RO_LACS_DUNGEONS && DungeonCount + (Greg && GregInLacsLogic ? 1 : 0) >= ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value<uint8_t>()) ||
|
||||
(ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS && GoldSkulltulaTokens >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value<uint8_t>());
|
||||
CanCompleteTriforce = TriforcePieces >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Value<uint8_t>();
|
||||
}
|
||||
|
||||
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount) {
|
||||
@@ -769,9 +770,12 @@ namespace Logic {
|
||||
|
||||
//Reset All Logic to false
|
||||
void LogicReset() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
//Settings-dependent variables
|
||||
IsKeysanity = Keysanity.Is(KEYSANITY_ANYWHERE) || Keysanity.Is(KEYSANITY_OVERWORLD) || Keysanity.Is(KEYSANITY_ANY_DUNGEON);
|
||||
AmmoCanDrop = AmmoDrops.IsNot(AMMODROPS_NONE);
|
||||
IsKeysanity = ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) ||
|
||||
ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) ||
|
||||
ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE);
|
||||
AmmoCanDrop = /*AmmoDrops.IsNot(AMMODROPS_NONE) TODO: AmmoDrop setting*/ true;
|
||||
|
||||
//Child item logic
|
||||
KokiriSword = false;
|
||||
@@ -897,7 +901,7 @@ namespace Logic {
|
||||
//Keys
|
||||
ForestTempleKeys = 0;
|
||||
//If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in vanilla FiT
|
||||
FireTempleKeys = IsKeysanity || Dungeon::FireTemple.IsMQ() ? 0 : 1;
|
||||
FireTempleKeys = IsKeysanity || ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsMQ() ? 0 : 1;
|
||||
WaterTempleKeys = 0;
|
||||
SpiritTempleKeys = 0;
|
||||
ShadowTempleKeys = 0;
|
||||
@@ -1018,7 +1022,7 @@ namespace Logic {
|
||||
HasBoots = false;
|
||||
IsChild = false;
|
||||
IsAdult = false;
|
||||
IsGlitched = Settings::Logic.Is(LOGIC_GLITCHED);
|
||||
IsGlitched = ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED);
|
||||
CanBlastOrSmash = false;
|
||||
CanChildAttack = false;
|
||||
CanChildDamage = false;
|
||||
@@ -1036,9 +1040,9 @@ namespace Logic {
|
||||
BigPoeKill = false;
|
||||
HookshotOrBoomerang = false;
|
||||
|
||||
BaseHearts = StartingHearts.Value<uint8_t>() + 1;
|
||||
BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).Value<uint8_t>() + 1;
|
||||
Hearts = 0;
|
||||
Multiplier = (DamageMultiplier.Value<uint8_t>() < 6) ? DamageMultiplier.Value<uint8_t>() : 10;
|
||||
Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Value<uint8_t>() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Value<uint8_t>() : 10;
|
||||
EffectiveHealth = 0;
|
||||
FireTimer = 0;
|
||||
WaterTimer = 0;
|
||||
@@ -1070,7 +1074,7 @@ namespace Logic {
|
||||
//Other
|
||||
AtDay = false;
|
||||
AtNight = false;
|
||||
Age = Settings::ResolvedStartingAge;
|
||||
Age = ctx->GetSettings()->ResolvedStartingAge();
|
||||
|
||||
//Events
|
||||
ShowedMidoSwordAndShield = false;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "menu.hpp"
|
||||
#include "playthrough.hpp"
|
||||
#include "randomizer.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "location_access.hpp"
|
||||
#include <spdlog/spdlog.h>
|
||||
@@ -19,11 +18,12 @@ namespace {
|
||||
bool seedChanged;
|
||||
uint16_t pastSeedLength;
|
||||
std::vector<std::string> presetEntries;
|
||||
Option* currentSetting;
|
||||
Rando::Option* currentSetting;
|
||||
} // namespace
|
||||
|
||||
std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks,
|
||||
std::string seedString) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
|
||||
srand(time(NULL));
|
||||
// if a blank seed was entered, make a random one
|
||||
@@ -42,11 +42,11 @@ std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t>
|
||||
return "";
|
||||
}
|
||||
|
||||
Settings::seedString = seedString;
|
||||
uint32_t seedHash = boost::hash_32<std::string>{}(Settings::seedString);
|
||||
Settings::seed = seedHash & 0xFFFFFFFF;
|
||||
ctx->GetSettings()->SetSeedString(seedString);
|
||||
uint32_t seedHash = boost::hash_32<std::string>{}(ctx->GetSettings()->GetSeedString());
|
||||
ctx->GetSettings()->SetSeed(seedHash & 0xFFFFFFFF);
|
||||
|
||||
int ret = Playthrough::Playthrough_Init(Settings::seed, cvarSettings, excludedLocations, enabledTricks);
|
||||
int ret = Playthrough::Playthrough_Init(ctx->GetSettings()->GetSeed(), cvarSettings, excludedLocations, enabledTricks);
|
||||
if (ret < 0) {
|
||||
if (ret == -1) { // Failed to generate after 5 tries
|
||||
printf("\n\nFailed to generate after 5 tries.\nPress B to go back to the menu.\nA different seed might be "
|
||||
@@ -60,21 +60,21 @@ std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t>
|
||||
}
|
||||
|
||||
// Restore settings that were set to a specific value for vanilla logic
|
||||
if (Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
for (Option* setting : Settings::vanillaLogicDefaults) {
|
||||
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
|
||||
for (Rando::Option* setting : ctx->GetSettings()->VanillaLogicDefaults) {
|
||||
setting->RestoreDelayedOption();
|
||||
}
|
||||
Settings::Keysanity.RestoreDelayedOption();
|
||||
ctx->GetOption(RSK_KEYSANITY).RestoreDelayedOption();
|
||||
}
|
||||
std::ostringstream fileNameStream;
|
||||
for (int i = 0; i < Settings::hashIconIndexes.size(); i++) {
|
||||
for (int i = 0; i < ctx->hashIconIndexes.size(); i++) {
|
||||
if (i) {
|
||||
fileNameStream << '-';
|
||||
}
|
||||
if (Settings::hashIconIndexes[i] < 10) {
|
||||
if (ctx->hashIconIndexes[i] < 10) {
|
||||
fileNameStream << '0';
|
||||
}
|
||||
fileNameStream << std::to_string(Settings::hashIconIndexes[i]);
|
||||
fileNameStream << std::to_string(ctx->hashIconIndexes[i]);
|
||||
}
|
||||
std::string fileName = fileNameStream.str();
|
||||
return "./Randomizer/" + fileName + ".json";
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "random.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||
#include <variables.h>
|
||||
#include "../option.h"
|
||||
|
||||
namespace Playthrough {
|
||||
|
||||
@@ -23,30 +25,29 @@ int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uin
|
||||
ctx->HintReset();
|
||||
Areas::AccessReset();
|
||||
|
||||
Settings::UpdateSettings(cvarSettings, excludedLocations, enabledTricks);
|
||||
ctx->GetSettings()->UpdateSettings(cvarSettings, excludedLocations, enabledTricks);
|
||||
// once the settings have been finalized turn them into a string for hashing
|
||||
std::string settingsStr;
|
||||
for (Menu* menu : Settings::GetAllOptionMenus()) {
|
||||
for (const Rando::OptionGroup& optionGroup : ctx->GetSettings()->GetOptionGroups()) {
|
||||
// don't go through non-menus
|
||||
if (menu->mode != OPTION_SUB_MENU) {
|
||||
if (optionGroup.GetContainsType() != Rando::OptionGroupType::SUBGROUP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < menu->settingsList->size(); i++) {
|
||||
Option* setting = menu->settingsList->at(i);
|
||||
if (setting->IsCategory(OptionCategory::Setting)) {
|
||||
settingsStr += setting->GetSelectedOptionText();
|
||||
for (Rando::Option* option : optionGroup.GetOptions()) {
|
||||
if (option->IsCategory(Rando::OptionCategory::Setting)) {
|
||||
settingsStr += option->GetSelectedOptionText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t finalHash = boost::hash_32<std::string>{}(std::to_string(Settings::seed) + settingsStr);
|
||||
uint32_t finalHash = boost::hash_32<std::string>{}(std::to_string(ctx->GetSettings()->GetSeed()) + settingsStr);
|
||||
Random_Init(finalHash);
|
||||
Settings::hash = std::to_string(finalHash);
|
||||
ctx->GetSettings()->SetHash(std::to_string(finalHash));
|
||||
|
||||
Logic::UpdateHelpers();
|
||||
|
||||
if (Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
|
||||
VanillaFill(); // Just place items in their vanilla locations
|
||||
} else { // Fill locations with logic
|
||||
int ret = Fill();
|
||||
@@ -58,7 +59,7 @@ int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uin
|
||||
GenerateHash();
|
||||
WriteIngameSpoilerLog();
|
||||
|
||||
if (Settings::GenerateSpoilerLog) {
|
||||
if (/*Settings::GenerateSpoilerLog TODO: do we ever not want to write a spoiler log?*/ true) {
|
||||
// write logs
|
||||
printf("\x1b[11;10HWriting Spoiler Log...");
|
||||
if (SpoilerLog_Write(cvarSettings[RSK_LANGUAGE])) {
|
||||
@@ -86,14 +87,15 @@ int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uin
|
||||
// used for generating a lot of seeds at once
|
||||
int Playthrough_Repeat(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks, int count /*= 1*/) {
|
||||
printf("\x1b[0;0HGENERATING %d SEEDS", count);
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
uint32_t repeatedSeed = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
Settings::seedString = std::to_string(rand() % 0xFFFFFFFF);
|
||||
repeatedSeed = boost::hash_32<std::string>{}(Settings::seedString);
|
||||
Settings::seed = repeatedSeed % 0xFFFFFFFF;
|
||||
ctx->GetSettings()->SetSeedString(std::to_string(rand() % 0xFFFFFFFF));
|
||||
repeatedSeed = boost::hash_32<std::string>{}(ctx->GetSettings()->GetSeedString());
|
||||
ctx->GetSettings()->SetSeed(repeatedSeed % 0xFFFFFFFF);
|
||||
//CitraPrint("testing seed: " + std::to_string(Settings::seed));
|
||||
ClearProgress();
|
||||
Playthrough_Init(Settings::seed, cvarSettings, excludedLocations, enabledTricks);
|
||||
Playthrough_Init(ctx->GetSettings()->GetSeed(), cvarSettings, excludedLocations, enabledTricks);
|
||||
printf("\x1b[15;15HSeeds Generated: %d\n", i + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../item_location.h"
|
||||
#include "location_access.hpp"
|
||||
#include "rando_main.hpp"
|
||||
#include "../context.h"
|
||||
// #include <soh/Enhancements/randomizer.h>
|
||||
#include <libultraship/bridge.h>
|
||||
#include <Context.h>
|
||||
@@ -17,9 +18,10 @@ void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarS
|
||||
// CVarSetString("gLoadedPreset", settingsFileName.c_str());
|
||||
|
||||
std::string fileName = LUS::Context::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations, enabledTricks, seedString).c_str());
|
||||
CVarSetString("gSpoilerLog", fileName.c_str());
|
||||
|
||||
CVarSave();
|
||||
CVarLoad();
|
||||
CVarSetInteger("gNewSeedGenerated", 1);
|
||||
Rando::Context::GetInstance()->SetSeedGenerated();
|
||||
Rando::Context::GetInstance()->SetSpoilerLoaded(false);
|
||||
Rando::Context::GetInstance()->SetPlandoLoaded(false);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,6 @@
|
||||
#include <map>
|
||||
#include "z64item.h"
|
||||
|
||||
using namespace Settings;
|
||||
|
||||
std::vector<ItemAndPrice> NonShopItems = {};
|
||||
|
||||
@@ -134,13 +133,14 @@ int GetPriceFromMax(int max) {
|
||||
// Get random price out of available "affordable prices", or just return 10 if Starter wallet is selected (no need to randomly select
|
||||
// from a single element)
|
||||
int GetPriceAffordable() {
|
||||
if (Settings::ShopsanityPrices.Is(RO_SHOPSANITY_PRICE_STARTER)) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (ctx->GetOption(RSK_SHOPSANITY_PRICES).Is(RO_SHOPSANITY_PRICE_STARTER)) {
|
||||
return 10;
|
||||
}
|
||||
|
||||
static const std::vector<int> affordablePrices = { 10, 105, 205, 505 };
|
||||
std::vector<int> priceList;
|
||||
uint8_t maxElements = Settings::ShopsanityPrices.Value<uint8_t>();
|
||||
uint8_t maxElements = ctx->GetOption(RSK_SHOPSANITY_PRICES).Value<uint8_t>();
|
||||
for (int i = 0; i < maxElements; i++) {
|
||||
priceList.push_back(affordablePrices.at(i));
|
||||
}
|
||||
@@ -148,8 +148,9 @@ int GetPriceAffordable() {
|
||||
}
|
||||
|
||||
int GetRandomShopPrice() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
// If Shopsanity prices aren't Balanced, but Affordable is on, don't GetPriceFromMax
|
||||
if (Settings::ShopsanityPricesAffordable.Is(true) && Settings::ShopsanityPrices.IsNot(RO_SHOPSANITY_PRICE_BALANCED)) {
|
||||
if (ctx->GetOption(RSK_SHOPSANITY_PRICES_AFFORDABLE).Is(true) && ctx->GetOption(RSK_SHOPSANITY_PRICES).IsNot(RO_SHOPSANITY_PRICE_BALANCED)) {
|
||||
return GetPriceAffordable();
|
||||
}
|
||||
|
||||
@@ -157,16 +158,16 @@ int GetRandomShopPrice() {
|
||||
int max = 0;
|
||||
|
||||
// check settings for a wallet tier selection and set max amount as method for setting true randomization
|
||||
if(Settings::ShopsanityPrices.Is(RO_SHOPSANITY_PRICE_STARTER)) {
|
||||
if(ctx->GetOption(RSK_SHOPSANITY_PRICES).Is(RO_SHOPSANITY_PRICE_STARTER)) {
|
||||
max = 19; // 95/5
|
||||
}
|
||||
else if (Settings::ShopsanityPrices.Is(RO_SHOPSANITY_PRICE_ADULT)) {
|
||||
else if (ctx->GetOption(RSK_SHOPSANITY_PRICES).Is(RO_SHOPSANITY_PRICE_ADULT)) {
|
||||
max = 40; // 200/5
|
||||
}
|
||||
else if (Settings::ShopsanityPrices.Is(RO_SHOPSANITY_PRICE_GIANT)) {
|
||||
else if (ctx->GetOption(RSK_SHOPSANITY_PRICES).Is(RO_SHOPSANITY_PRICE_GIANT)) {
|
||||
max = 100; // 500/5
|
||||
}
|
||||
else if (Settings::ShopsanityPrices.Is(RO_SHOPSANITY_PRICE_TYCOON)) {
|
||||
else if (ctx->GetOption(RSK_SHOPSANITY_PRICES).Is(RO_SHOPSANITY_PRICE_TYCOON)) {
|
||||
max = 199; // 995/5
|
||||
}
|
||||
if (max != 0) {
|
||||
@@ -205,13 +206,14 @@ int16_t GetRandomScrubPrice() {
|
||||
|
||||
//Get 1 to 4, or a random number from 1-4 depending on shopsanity setting
|
||||
int GetShopsanityReplaceAmount() {
|
||||
if (Settings::Shopsanity.Is(SHOPSANITY_ONE)) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_ONE_ITEM)) {
|
||||
return 1;
|
||||
} else if (Settings::Shopsanity.Is(SHOPSANITY_TWO)) {
|
||||
} else if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_TWO_ITEMS)) {
|
||||
return 2;
|
||||
} else if (Settings::Shopsanity.Is(SHOPSANITY_THREE)) {
|
||||
} else if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_THREE_ITEMS)) {
|
||||
return 3;
|
||||
} else if (Settings::Shopsanity.Is(SHOPSANITY_FOUR)) {
|
||||
} else if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_FOUR_ITEMS)) {
|
||||
return 4;
|
||||
} else { //Random, get number in [1, 4]
|
||||
return Random(1, 5);
|
||||
@@ -220,195 +222,195 @@ int GetShopsanityReplaceAmount() {
|
||||
|
||||
//Initialize the table of trick names with an easy, medium, and hard name for each language
|
||||
void InitTrickNames() {
|
||||
trickNameTable[GI_SWORD_KOKIRI] = {
|
||||
trickNameTable[RG_KOKIRI_SWORD] = {
|
||||
Text{"Korok Sword", "Épée Korok", "Espada Korok"},
|
||||
Text{"Hero's Sword", "Épée du Héros", "Espada del héroe"},
|
||||
Text{"Razor Sword", "Lame Rasoir", "Espada de esmeril"}};
|
||||
trickNameTable[0xE0] = { //Master Sword without the GI enum
|
||||
trickNameTable[RG_MASTER_SWORD] = { //Master Sword without the GI enum
|
||||
Text{"Goddess Sword", "Épée de la déesse", "Espada Divina"},
|
||||
Text{"Gilded Sword", "Excalibur", "Espada de los Sabios"},
|
||||
Text{"Magical Sword", "Lame dorée", "Fay"}};
|
||||
trickNameTable[GI_SWORD_KNIFE] = {
|
||||
trickNameTable[RG_GIANTS_KNIFE] = {
|
||||
Text{"Medigoron's Sword", "l'Épée de Medigoron", "La espada de Medigoron"},
|
||||
Text{"Razor Sword", "Lame Rasoir", "Espada de esmeril"},
|
||||
Text{"Royal Claymore", "Claymore Royale", "Royal Claymore"}};
|
||||
trickNameTable[GI_SWORD_BGS] = {
|
||||
trickNameTable[RG_BIGGORON_SWORD] = {
|
||||
Text{"Power Sword", "Épée de Puissance", "Espada de poder"},
|
||||
Text{"Fierce Deity Sword", "Épée du dieu démon", "Espada de la Fiera Deidad"},
|
||||
Text{"Tempered Sword", "Épée de Légende Nv.2", "Espada Maestra mejorada"},
|
||||
Text{"Biggoron's Knife", "Lame de Grogoron", "Daga de Biggoron"}};
|
||||
trickNameTable[GI_SHIELD_DEKU] = {
|
||||
trickNameTable[RG_DEKU_SHIELD] = {
|
||||
Text{"Boko Shield", "Bouclier Boko", "Escudo Boko"},
|
||||
Text{"Ordon Shield", "Bouclier de Toal", "Escudo de Ordon"},
|
||||
Text{"Wooden Shield", "Bouclier de Bois", "Escudo de madera"}};
|
||||
trickNameTable[GI_SHIELD_HYLIAN] = {
|
||||
trickNameTable[RG_HYLIAN_SHIELD] = {
|
||||
Text{"Hyrule Shield", "Bouclier d'Hyrule", "Escudo Hylian"},
|
||||
Text{"Goddess Shield", "Bouclier Sacré", "Escudo Divino"},
|
||||
Text{"Hero's Shield", "Bouclier du Héros", "Escudo del héroe"}};
|
||||
trickNameTable[GI_SHIELD_MIRROR] = {
|
||||
trickNameTable[RG_MIRROR_SHIELD] = {
|
||||
Text{"Magic Mirror", "Miroir Magique", "Escudo mágico"},
|
||||
Text{"Magical Shield", "Bouclier Magique", "Escudo arcano"},
|
||||
Text{"Mirror of Twilight", "Miroir des Ombres", "Espejo del Crepúsculo"}};
|
||||
trickNameTable[GI_TUNIC_GORON] = {
|
||||
trickNameTable[RG_GORON_TUNIC] = {
|
||||
Text{"Gerudo Top", "Tunique Gerudo", "Pechera gerudo"},
|
||||
Text{"Flamebreaker Armor", "Armure de Pierre", " Armadura ignífuga"},
|
||||
Text{"Red Mail", "Habits Rouges", "Ropas rojas"}};
|
||||
trickNameTable[GI_TUNIC_ZORA] = {
|
||||
trickNameTable[RG_ZORA_TUNIC] = {
|
||||
Text{"Rito Tunic", "Tunique Rito", "Sayo rito"},
|
||||
Text{"Mermaid Suit", "Costume de sirène", "Costume de sirène"},
|
||||
Text{"Zora Armor", "Armure Zora", "Túnica Zora"},
|
||||
Text{"Blue Mail", "Habits Bleus", "Ropas azules"}};
|
||||
trickNameTable[GI_BOOTS_IRON] = {
|
||||
trickNameTable[RG_IRON_BOOTS] = {
|
||||
Text{"Iron Hoofs", "Patins de Plomb", "Botas férreas"},
|
||||
Text{"Snow Boots", "Bottes de Neige", "Botas de nieve"},
|
||||
Text{"Red Boots", "Bottes rouges", "Botas rojas"},
|
||||
Text{"Zora Greaves", "Bottes Zora", "Zora Greaves"},
|
||||
Text{"Boots of Power", "Bottes de Puissance", "Botas de plomo"}};
|
||||
trickNameTable[GI_BOOTS_HOVER] = {
|
||||
trickNameTable[RG_HOVER_BOOTS] = {
|
||||
Text{"Hover Hoofs", "Patins des airs", "Botas flotadoras"},
|
||||
Text{"Golden Boots", "Bottes dorées", "Botas de Oro"},
|
||||
Text{"Pegasus Boots", "Bottes pégase", "Botas de Pegaso"},
|
||||
Text{"Boots of Speed", "Bottes de vitesse", "Botas del desierto"}};
|
||||
trickNameTable[GI_WEIRD_EGG] = {
|
||||
trickNameTable[RG_WEIRD_EGG] = {
|
||||
Text{"Poached Egg", "Oeuf à la coque", "Huevo pasado"},
|
||||
Text{"Lon Lon Egg", "Oeuf Lon Lon", "Huevo Lon Lon"},
|
||||
Text{"Zora Egg", "Oeuf Zora", "Huevo Zora"}};
|
||||
trickNameTable[GI_LETTER_ZELDA] = {
|
||||
trickNameTable[RG_ZELDAS_LETTER] = {
|
||||
Text{"Ruto's Letter", "Lettre de Ruto", "Carta de Ruto"},
|
||||
Text{"Royal Letter", "Lettre Eoyale", "Carta para Kafei"},
|
||||
Text{"Zelda's Business Card", "Carte d'affaires de Zelda", "Carta"},
|
||||
Text{"Letter to Kafei", "Lettre pour Kafei", "Carta para Kafei "},
|
||||
Text{"Goat's Letter", "Lettre de la Chèvre", "Carta de la Cabra"},
|
||||
Text{"Maggie's Letter", "Lettre de Maggy", "Carta de Dolores"}};
|
||||
trickNameTable[GI_BOOMERANG] = {
|
||||
trickNameTable[RG_BOOMERANG] = {
|
||||
Text{"Banana", "Banane", "Plátano"},
|
||||
Text{"Prank Fetch Toy", "Inséparable Bâtonnet", "Bumerang"},
|
||||
Text{"Gale Boomerang", "Boomerang Tornade", "Bumerán tornado"},
|
||||
Text{"Magic Boomerang", "Boomerang Magique", "Bumerán mágico"}};
|
||||
trickNameTable[GI_LENS] = {
|
||||
trickNameTable[RG_LENS_OF_TRUTH] = {
|
||||
Text{"Sheikah-leidoscope", "Sheikah-léidoscope", "Monóculo de la Verdad"},
|
||||
Text{"Sheikah Sensor", "Sonar Sheikah", "Sensor Sheikah"},
|
||||
Text{"Crystal of Vision", "Cristal de Vision", "Cristal de Visión"},
|
||||
Text{"Magnifying Lens", "Loupe", "Lente Aumentadora"}};
|
||||
trickNameTable[GI_HAMMER] = {
|
||||
trickNameTable[RG_MEGATON_HAMMER] = {
|
||||
Text{"Goron Gavel", "Masse Perforatrice", "Mazo Goron"},
|
||||
Text{"Magic Hammer", "Marteau Magique", "Martillo mágico"},
|
||||
Text{"Skull Hammer", "Maillet Ressort", "Martillo de hierro"}};
|
||||
trickNameTable[GI_STONE_OF_AGONY] = {
|
||||
trickNameTable[RG_STONE_OF_AGONY] = {
|
||||
Text{"Cave Charm", "Charme de grotte", "Amuleto de la cueva"},
|
||||
Text{"Stone of Agahnim", "Fragment d'Agahnim", "Piedra de Agahnim"},
|
||||
Text{"Shard of Agony", "Fragment de Souffrance", "Piedra de la Agonía"},
|
||||
Text{"Pirate's Charm", "Pierre de Pirate", "Amuleto Pirata"}};
|
||||
trickNameTable[GI_DINS_FIRE] = {
|
||||
trickNameTable[RG_DINS_FIRE] = {
|
||||
Text{"Eldin's Fire", "Feu d'Eldin", "Fuego de Eldin"},
|
||||
Text{"Din's Blaze", "Flamme de Din", "Poder de Din"},
|
||||
Text{"Magic Lantern", "Lanterne Magique", "Linterna mágica"},
|
||||
Text{"Ether Medallion", "Médaillon d'Éther", "Medallón de Tesoro"},
|
||||
Text{"Bombos Medallion", "Médaillon des Flammes", "Medallón del Temblor"}};
|
||||
trickNameTable[GI_FARORES_WIND] = {
|
||||
trickNameTable[RG_FARORES_WIND] = {
|
||||
Text{"Faron's Wind", "Vent de Firone", "Viento de Farone"},
|
||||
Text{"Farore's Windfall", "Zéphyr de Farore", "Valor de Farore"},
|
||||
Text{"Tingle Air", "Tingle Air", "Tingle de aire"},
|
||||
Text{"Travel Medallion", "Amulette de téléportation", "Medallón Maligno"},
|
||||
Text{"Irene's Taxi", "Le taxi d'Aëline", "El taxi de Airín"}};
|
||||
trickNameTable[GI_NAYRUS_LOVE] = {
|
||||
trickNameTable[RG_NAYRUS_LOVE] = {
|
||||
Text{"Lanayru's Love", "Amour de Lanelle", "Amor de Lanayru"},
|
||||
Text{"Nayru's Passion", "Passion de Nayru", "Sabiduría de Nayru"},
|
||||
Text{"Tingle Shield", "Bouclier Tingle", "Escudo de hormigueo"},
|
||||
Text{"Shield Spell", "Bouclier Magique", "Hechizo de Protección"},
|
||||
Text{"Magic Armor", "Armure Magique", "Armadura mágica"}};
|
||||
trickNameTable[GI_ARROW_FIRE] = {
|
||||
trickNameTable[RG_FIRE_ARROWS] = {
|
||||
Text{"Fire Rod", "Baguette de feu", "Cetro de fuego"},
|
||||
Text{"Bomb Arrow", "Flèche-Bombe", "Flecha bomba"},
|
||||
Text{"Red Candle", "Bougie Rouge", "Vela roja"}};
|
||||
trickNameTable[GI_ARROW_ICE] = {
|
||||
trickNameTable[RG_ICE_ARROWS] = {
|
||||
Text{"Ice Rod", "Baguette des Glaces", "Cetro de Hielo"},
|
||||
Text{"Ancient Arrow", "Flèche Archéonique", "Flecha ancestral"},
|
||||
Text{"Ice Trap Arrow", "Flèche de Piège de Glace", "Cetro de hielo"}};
|
||||
trickNameTable[GI_ARROW_LIGHT] = {
|
||||
trickNameTable[RG_LIGHT_ARROWS] = {
|
||||
Text{"Wind Arrow", "Flèche de Vent", "Flecha del Viento"},
|
||||
Text{"Wand of Gamelon", "Baguette de Gamelon", "Varita de Gamelón"},
|
||||
Text{"Shock Arrow", "Flèches Électriques", "Flecha eléctrica"},
|
||||
Text{"Silver Arrow", "Flèches d'Argent", "Flecha de plata"}};
|
||||
trickNameTable[GI_GERUDO_CARD] = {
|
||||
trickNameTable[RG_GERUDO_MEMBERSHIP_CARD] = {
|
||||
Text{"Desert Title Deed", "Abonnement Gerudo", "Escritura del desierto"},
|
||||
Text{"Sickle Moon Flag", "Drapeau du croissant de lune", "Bandera de la Luna Creciente"},
|
||||
Text{"Complimentary ID", "Bon de félicitation", "Cupón especial"},
|
||||
Text{"Gerudo's Card", "Carte Goron", "Tóken Gerudo"},
|
||||
Text{"Gerudo's Membership Card", "Autographe de Nabooru", "Tarjeta Gerudo"}};
|
||||
|
||||
trickNameTable[0xC9] = {
|
||||
trickNameTable[RG_MAGIC_BEAN_PACK] = {
|
||||
Text{"Funky Bean Pack", "Paquet de Fèves Magiques", "Lote de frijoles mágicos"},
|
||||
Text{"Grapple Berries", "Baies de grappin", "Bayas de garfio"},
|
||||
Text{"Crenel Bean Pack", "Paquet de Haricots Gonggle", "Lote de alubias mágicas"},
|
||||
Text{"Mystical Seed Pack", "Pack de graines mystiques", "Paquete de semillas místicas"}};
|
||||
trickNameTable[0xB8] = {
|
||||
trickNameTable[RG_DOUBLE_DEFENSE] = {
|
||||
Text{"Diamond Hearts", "Coeurs de Diamant", "Contenedor de diamante"},
|
||||
Text{"Double Damage", "Double Souffrance", "Doble daño receptivo"},
|
||||
Text{"Quadruple Defence", "Quadruple Défence", "Defensa cuádruple"}};
|
||||
|
||||
trickNameTable[GI_POCKET_EGG] = {
|
||||
trickNameTable[RG_POCKET_EGG] = {
|
||||
Text{"Arpagos Egg", "Oeuf d'Arpagos", "Huevo de Arpagos"},
|
||||
Text{"Lon Lon Egg", "oeuf Lon Lon", "Huevo Lon Lon"},
|
||||
Text{"Zora Egg", "oeuf Zora", "Huevo del Pez Viento"}};
|
||||
trickNameTable[GI_POCKET_CUCCO] = {
|
||||
trickNameTable[RG_POCKET_EGG] = {
|
||||
Text{"D.I.Y. Alarm Clock", "Réveille-matin improvisé", "Alarma emplumada portátil"},
|
||||
Text{"Kakariko Cucco", "Cocotte Cocorico", "Cuco de Kakariko"},
|
||||
Text{"Hatched Cucco", "Cocotte éclose", "Pollo de bolsillo"}};
|
||||
trickNameTable[GI_COJIRO] = {
|
||||
trickNameTable[RG_COJIRO] = {
|
||||
Text{"Blucco", "Chair-Qui-Poule", "Cucazul"},
|
||||
Text{"Piyoko", "Piyoko", "Piyoko"},
|
||||
Text{"Dark Cucco", "Cocotte Sombre", "Cucco oscuro"},
|
||||
Text{"Grog's Cucco", "Cocotte de Grog", "Cuco de Grog"}};
|
||||
trickNameTable[GI_ODD_MUSHROOM] = {
|
||||
trickNameTable[RG_ODD_MUSHROOM] = {
|
||||
Text{"Magic Mushroom", "Champignon magique", "Champiñón mágico"},
|
||||
Text{"Endura Shroom", "Champi Vigueur", "Champiñón del bosque"},
|
||||
Text{"Sleepy Toadstool", "Crapaud Fatigué", "Seta durmiente"},
|
||||
Text{"Mushroom", "Champignon", "Seta"}};
|
||||
trickNameTable[GI_ODD_POTION] = {
|
||||
trickNameTable[RG_ODD_POTION] = {
|
||||
Text{"Odd Medicine", "Élixir suspect", "Poción rara"},
|
||||
Text{"Granny's Poultice", "Mixture de Granny", "Medicina de la abuela"},
|
||||
Text{"Mushroom Poultice", "Mixture de champignon", "Medicina de champiñones"},
|
||||
Text{"Secret Medicine", "Médicament", "Pócima secreta"},
|
||||
Text{"Mushroom Spores", "Spores de Champignons", "Esporas de hongos"},
|
||||
Text{"Hanyu Spore", "Hanyu Spore", "Espora Hanyu"}};
|
||||
trickNameTable[GI_SAW] = {
|
||||
trickNameTable[RG_POACHERS_SAW] = {
|
||||
Text{"Carpenter's Saw", "Scie du charpentier", "Sierra del carpintero"},
|
||||
Text{"Poacher's Sword", "Hache du chasseur", "Espada del capataz"},
|
||||
Text{"Ancient Bladesaw", "Longue Épée Archéonique", "Mandoble ancestral"},
|
||||
Text{"Woodcutter's Axe", "Hache du Bûcheron", "Hacha de leñador"},
|
||||
Text{"Grog's Saw", "Scie de Grog", "Sierra del Cazador Furtivo"}};
|
||||
trickNameTable[GI_SWORD_BROKEN] = {
|
||||
trickNameTable[RG_BROKEN_SWORD] = {
|
||||
Text{"Broken Biggoron's Sword", "Épée brisée de Grogoron", "Espada de Biggoron rota"},
|
||||
Text{"Broken Giant's Knife", "Lame des Géants brisée", "Daga gigante rota"},
|
||||
Text{"Broken Noble Sword", "Épée noble brisée", "Espada noble rota"},
|
||||
Text{"Broken Picori Blade", "Épée Minish brisée", "Espada minish rota"},
|
||||
Text{"Decayed Master Sword", "Épée de légende pourrie", "Espada decadente de leyenda"}};
|
||||
trickNameTable[GI_PRESCRIPTION] = {
|
||||
trickNameTable[RG_PRESCRIPTION] = {
|
||||
Text{"Biggoron's Prescription", "Ordonnance de Grogoron", "Receta de Biggoron"},
|
||||
Text{"Eyedrop Prescription", "Ordonnance de gouttes", "Receta ocular"},
|
||||
Text{"Urgent Prescription", "Ordonnance urgente", "Prescripción"},
|
||||
Text{"Swordsman's Scroll", "Précis d'escrime", "Esgrimidorium"},
|
||||
Text{"Portrait of Oren", "Portrait d'Orlène", "Retrato de Oren"},
|
||||
Text{"Letter to King Zora", "Lettre au roi Zora", "Carta al Rey Zora"}};
|
||||
trickNameTable[GI_FROG] = {
|
||||
trickNameTable[RG_EYEBALL_FROG] = {
|
||||
Text{"Don Gero", "Don Gero", "Don Gero"},
|
||||
Text{"Hot-Footed Frog", "Grenouille à pieds chauds", "Rana de patas calientes"},
|
||||
Text{"Lost Swordsmith", "Forgeron perdu", "Espadachín perdido"},
|
||||
Text{"Eyedrop Frog", "Grenouille-qui-louche", "Globo Ocular de Rana"}};
|
||||
trickNameTable[GI_EYEDROPS] = {
|
||||
trickNameTable[RG_EYEDROPS] = {
|
||||
Text{"Biggoron's Eyedrops", "Gouttes de Grogoron", "Gotas de Biggoron"},
|
||||
Text{"Hyrule's Finest Eyedrops", "Eau du Lac Hylia", "Gotas oculares"},
|
||||
Text{"Moon's Tear", "Larme de Lune", "Lágrima de Luna"},
|
||||
Text{"Engine Grease", "Graisse moteur", "Grasa del motor"},
|
||||
Text{"Zora Perfume", "Parfum Zora", "Perfume Zora"}};
|
||||
trickNameTable[GI_CLAIM_CHECK] = {
|
||||
trickNameTable[RG_CLAIM_CHECK] = {
|
||||
Text{"Clay Check", "Certificat Grogoron", "Comprobante de Reclamación"},
|
||||
Text{"Ancient Tablet", "Stèle ancienne", "Litografía arcana"},
|
||||
Text{"Sheikah Slate", "Tablette Sheikah", "Piedra Sheikah"},
|
||||
Text{"Cyclone Slate", "Ardoise des tornades", "Pizarra de los Torbellinos"}};
|
||||
|
||||
trickNameTable[GI_SKULL_TOKEN] = {
|
||||
trickNameTable[RG_GOLD_SKULLTULA_TOKEN] = {
|
||||
Text{"Skulltula Token", "Bon de Skulltula dorée", "Símbolo de Skulltula"},
|
||||
Text{"Golden Skulltula Spirit", "Pièce de Skulltula dorée", "Tóken de Skulltula Dorada"},
|
||||
Text{"Gold Walltula Token", "Jeton de Walltula dorée", "Skulltula dorada"},
|
||||
@@ -416,75 +418,75 @@ void InitTrickNames() {
|
||||
Text{"Gratitude Crystal", "Cristal de gratitude", "Gema de gratitud"},
|
||||
Text{"Korok Seed", "Noix korogu", "Semilla de kolog"}};
|
||||
|
||||
trickNameTable[0x80] = {
|
||||
trickNameTable[RG_PROGRESSIVE_HOOKSHOT] = {
|
||||
Text{"Progressive Grappling Hook", "Lance-chaîne (prog.)", "Garra progresiva"},
|
||||
Text{"Progressive Clawshot", "Grappin-griffe (prog.)", "Zarpa progresiva"},
|
||||
Text{"Progressive Gripshot", "Grappince (prog.)", "Enganchador progresivo"},
|
||||
Text{"Progressive Rope", "Corde (prog.)", "Cuerda progresivo"}};
|
||||
trickNameTable[0x81] = {
|
||||
trickNameTable[RG_PROGRESSIVE_STRENGTH] = {
|
||||
Text{"Power Glove", "Gant de Puissance (prog.)", "Guanteletes progresivos"},
|
||||
Text{"Power Bracelet", "Bracelet de Force (prog.)", "Brasaletes progresivos"},
|
||||
Text{"Magic Bracelet", "Bracelet Magique (prog.)", "Manoplas progresivas"}};
|
||||
trickNameTable[0x82] = {
|
||||
trickNameTable[RG_PROGRESSIVE_BOMB_BAG] = {
|
||||
Text{"Progressive Bomb Capacity", "Capacité de bombes (prog.)", "Mayor capacidad de bombas"},
|
||||
Text{"Progressive Bomb Pack", "Paquet de bombes (prog.)", "Zurrón de bombas progresivo"},
|
||||
Text{"Progressive Bomb Box", "Boîte à bombes (prog.)", "Bolsa de bombas progresiva"},
|
||||
Text{"Progressive Blast Mask", "Masque d'Explosion (prog.)", "Máscara explosiva progresiva"},
|
||||
Text{"Progressive Powder Kegs", "Baril de Poudre (prog.)", "Barril de polvo progresivo"},
|
||||
Text{"Progressive Remote Bombs", "Bombes à distance (prog.)", "Bombas remotas progresivas"}};
|
||||
trickNameTable[0x83] = {
|
||||
trickNameTable[RG_PROGRESSIVE_BOW] = {
|
||||
Text{"Progressive Arrow Capacity", "Capacité de flèches (prog.)", "Mayor capacidad de flechas"},
|
||||
Text{"Progressive Hero's Bow", "Arc du héros (prog.)", "Arco del héroe progresivo"},
|
||||
Text{"Progressive Arrow Holder", "Arbalète (prog.)", "Ballesta progresiva"},
|
||||
Text{"Progressive Crossbow", "Arbalète (prog.)", "Ballesta progresiva"},
|
||||
Text{"Progressive Sacred Bow", "Arc sacré (prog)", "Arco Sagrado Progresivo"},
|
||||
Text{"Progressive Lynel Bow", "Arc de Lynel (prog.)", "Arco de centaleón Progresivo"}};
|
||||
trickNameTable[0x84] = {
|
||||
trickNameTable[RG_PROGRESSIVE_SLINGSHOT] = {
|
||||
Text{"Progressive Seed Capacity", "Capacité de graines (prog.)", "Mayor capacidad de semillas"},
|
||||
Text{"Progressive Catapult", "Catapulte (prog.)", "Catapulta progresiva"},
|
||||
Text{"Progressive Scattershot", "Lance-Pierre rafale (prog.)", "Resortera múltiple progresiva"},
|
||||
Text{"Progressive Seed Launcher", "Lanceur de semences (prog.)", "Lanzador de semillas progresivo"},
|
||||
Text{"Progressive Seed Satchel", "Sac de graines (prog.)", "Bolsa de semillas progresiva"}};
|
||||
trickNameTable[0x85] = {
|
||||
trickNameTable[RG_PROGRESSIVE_WALLET] = {
|
||||
Text{"Progressive Rupee Capacity", "Capacité de rubis (prog.)", "Mayor capacidad de rupias"},
|
||||
Text{"Progressive Purse", "Sacoche (prog.)", "Cartera de rupias progresiva"},
|
||||
Text{"Progressive Rupee Bag", "Sac à rubis (prog.)", "Zurrón de rupias progresivo"},
|
||||
Text{"Progressive Rupoor Capacity", "Capacité de Roupir (prog.)", "Capacidad progresiva Rupobre"},
|
||||
Text{"Progressive Spoils Bag", "Sac à Butin (prog.)", "Bolsa de trofeos progresiva"},
|
||||
Text{"Progressive Ruby Bag", "Capacité du sac Ruby (prog.)", "Bolso Ruby progresivo"}};
|
||||
trickNameTable[0x86] = {
|
||||
trickNameTable[RG_PROGRESSIVE_SCALE] = {
|
||||
Text{"Progressive Flippers", "Palmes de Zora (prog.)", "Aletas de zora progresiva"},
|
||||
Text{"Progressive Dragon's Scale", "Écaille du dragon d'eau (prog.)", "Escama dragón acuático progresiva"},
|
||||
Text{"Progressive Diving Ability", "Plongée (prog.)", "Buceo progresivo"},
|
||||
Text{"Progressive Pearl", "Perle (prog.)", "Perla progresiva"},
|
||||
Text{"Progressive Scute", "Bulle (prog.)", "Fragmento Zora progresivo"}};
|
||||
trickNameTable[0x87] = {
|
||||
trickNameTable[RG_PROGRESSIVE_NUT_UPGRADE] = {
|
||||
Text{"Progressive Nut Pack", "Paquet de noix (prog.)", "Mayor capacidad de semillas"},
|
||||
Text{"Progressive Bait Bag", "Sac à Appâts (prog.)", "Bolsa de cebo progresiva"},
|
||||
Text{"Progressive Pear Capacity", "Capacité de poire (prog.)", "Capacidad progresiva de pera"},
|
||||
Text{"Progressive Nut Bag", "Sac de noix (prog.)", "Bolsa de nueces progresiva"},
|
||||
Text{"Progressive Husk Capacity", "Capacité de noisettes (prog.)", "Mayor capacidad de castañas"}};
|
||||
trickNameTable[0x88] = {
|
||||
trickNameTable[RG_PROGRESSIVE_STICK_UPGRADE] = {
|
||||
Text{"Progressive Stick Bag", "Sac de bâtons (prog.)", "Mayor capacidad de ramas deku"},
|
||||
Text{"Progressive Stick Pack", "Paquet de bâtons Mojo (prog.)", "Mayor capacidad de bastones"},
|
||||
Text{"Progressive Branch Capacity", "Capacité de la succursale (prog.)", "Capacidad progresiva de la sucursal"},
|
||||
Text{"Progressive Rod Capacity", "Capacité de tiges (prog.)", "Mayor capacidad de cetros deku"}};
|
||||
trickNameTable[0x89] = {
|
||||
trickNameTable[RG_PROGRESSIVE_BOMBCHUS] = {
|
||||
Text{"Progressive Bomblings", "Bombinsectes (prog.)", "Bombinsectos progresivos"},
|
||||
Text{"Progressive Sentrobe Bombs", "Bombe de Sphérodrone (prog.)", "Bomba de helicobot progresivo"},
|
||||
Text{"Progressive Bomb-ombs", "Bombe Soldat (prog.)", "Soldado bomba progresivo"},
|
||||
Text{"Progressive Missiles", "Missiles (prog.)", "Misiles progresivos"},
|
||||
Text{"Progressive Bombchu Bag", "Sac à Bombchu (prog.)", "Bombachus progresivos"}};
|
||||
trickNameTable[0x8A] = {
|
||||
trickNameTable[RG_PROGRESSIVE_MAGIC_METER] = {
|
||||
Text{"Progressive Stamina Meter", "Jauge d'endurance (prog.)", "Medidor de vigor progresivo"},
|
||||
Text{"Progressive Energy Gauge", "Jauge d'énergie (prog.)", "Medidor de energía progresivo"},
|
||||
Text{"Progressive Magic Powder", "Poudre magique (prog.)", "Medidor de carga progresivo"}};
|
||||
trickNameTable[0x8B] = {
|
||||
trickNameTable[RG_PROGRESSIVE_OCARINA] = {
|
||||
Text{"Progressive Memento", "Souvenir (prog.)", "Silbato progresivo"},
|
||||
Text{"Progressive Whistle", "Siffler (prog.)", "Silbido progresivo"},
|
||||
Text{"Progressive Flute", "Flûte (prog.)", "Flauta progresiva"},
|
||||
Text{"Progressive Recorder", "Harmonica (prog.)", "Armónica progresiva"}};
|
||||
trickNameTable[0xD4] = {
|
||||
trickNameTable[RG_PROGRESSIVE_GORONSWORD] = {
|
||||
Text{"Progressive Titan Blade", "Lame des Titans (prog.)", "Hoja del Titán progresiva"},
|
||||
Text{"Progressive Goron Knife", "Lame Goron (prog.)", "Daga Goron progresiva"},
|
||||
Text{"Progressive Giant Sword", "Épée géante (prog.)", "Espada gigante progresiva"},
|
||||
@@ -492,212 +494,212 @@ void InitTrickNames() {
|
||||
Text{"Progressive Power Sword", "Épée de Puissance (prog.)", "Espada de poder progresiva"},
|
||||
Text{"Progressive Big Stabby", "Gros coup de poignard (prog.)", "Gran puñalada progresiva"}};
|
||||
|
||||
trickNameTable[0x0F] = {
|
||||
trickNameTable[RG_EMPTY_BOTTLE] = {
|
||||
Text{"Empty Canteen", "Cantine vide", "cantimplora vacía"},
|
||||
Text{"Vial of Winds", "Fiole de vents", "Vial de Vientos"},
|
||||
Text{"Tingle Bottle", "Flacon de Tingle", "Botella de Tingle"},
|
||||
Text{"Magic Bottle", "Flacon magique", "Frasco feérico"},
|
||||
Text{"Glass Bottle", "Flacon de verre", "Botella de cristal"},
|
||||
Text{"Bottle with Water", "Flacon d'eau", "Botella Tingle"}};
|
||||
trickNameTable[0x14] = {
|
||||
trickNameTable[RG_BOTTLE_WITH_MILK] = {
|
||||
Text{"Bottle with Chateau Romani", "Flacon de cuvée Romani", "Botella de Reserva Romani"},
|
||||
Text{"Bottle with Premium Milk", "Flacon avec lait de qualité supérieure", "Biberón con leche Premium"},
|
||||
Text{"Bottle with Mystery Milk", "Flacon de lait grand cru", "Botella de leche extra"},
|
||||
Text{"Bottle with Fresh Milk", "Flacon de lait frais", "Botella de leche fresca"},};
|
||||
trickNameTable[0x8C] = {
|
||||
trickNameTable[RG_BOTTLE_WITH_RED_POTION] = {
|
||||
Text{"Bottle with Red Chu Jelly", "Flacon de gelée Chuchu rouge", "Jugo de Chuchu Rojo"},
|
||||
Text{"Bottle with Hibiscus Potion", "Flacon de potion de Hibiscus", "Botella de poción de Hibisco"},
|
||||
Text{"Bottle with Medicine of Life", "Flacon d'élixir rouge", "Botella de medicina de la vida"},
|
||||
Text{"Bottle with Heart Potion", "Flacon de potion de soin", "Botella de poción de salud"}};
|
||||
trickNameTable[0x8D] = {
|
||||
trickNameTable[RG_BOTTLE_WITH_GREEN_POTION] = {
|
||||
Text{"Bottle with Green Chu Jelly", "Flacon de gelée Chuchu verte", "Jugo de Chuchu Verde"},
|
||||
Text{"Bottle with Lamp Oil", "Flacon de Huile à lanterne", "Botella de Aceite de candil "},
|
||||
Text{"Bottle with Medicine of Magic", "Flacon d'élixir vert", "Botella de medicina mágica"},
|
||||
Text{"Bottle with Stamina Potion", "Flacon d'Endurol", "Botella de elixir vigorizante"}};
|
||||
trickNameTable[0x8E] = {
|
||||
trickNameTable[RG_BOTTLE_WITH_BLUE_POTION] = {
|
||||
Text{"Bottle with Blue Chu Jelly", "Flacon de gelée Chuchu bleue", "Jugo de Chuchu Azul"},
|
||||
Text{"Bottle with Water of Life", "Flacon d'élixir bleu", "Botella de agua de la vida"},
|
||||
Text{"Bottle with Air Potion", "Flacon de potion d'oxygène", "Botella de oxígeno"}};
|
||||
trickNameTable[0x8F] = {
|
||||
trickNameTable[RG_BOTTLE_WITH_FAIRY] = {
|
||||
Text{"Bottle with Forest Firefly", "Flacon avec une luciole", "Luciérnaga del bosque"},
|
||||
Text{"Bottle with Deku Princess", "Flacon avec Deku Princess", "Botella con Deku Princess"},
|
||||
Text{"Bottle with Stray Fairy", "Flacon avec une fée perdue", "Hada perdida en una botella"}};
|
||||
trickNameTable[0x90] = {
|
||||
trickNameTable[RG_BOTTLE_WITH_FISH] = {
|
||||
Text{"Bottle with Small Jabu-Jabu", "Flacon avec mini Jabu-Jabu", "Lord Chapu-Chapu embotellado"},
|
||||
Text{"Bottle with Reekfish", "Flacon avec Reekfish", "Reekfish embotellada"},
|
||||
Text{"Bottle with Hyrule Bass", "Flacon avec perche d'Hyrule", "Locha de Hyrule embotellada"},
|
||||
Text{"Bottle with Hyrule Loach", "Flacon avec loche d'Hyrule", "Perca de Términa embotellada"}};
|
||||
trickNameTable[0x91] = {
|
||||
trickNameTable[RG_BOTTLE_WITH_BLUE_FIRE] = {
|
||||
Text{"Bottle with Will-O-Wisp", "Flacon avec feu follet", "Botella de llama azul"},
|
||||
Text{"Bottle with Ancient Flame", "Flacon de flamme ancienne", "Botella de fuego ancestral"},
|
||||
Text{"Bottle with a Blue Candle", "Flacon avec une bougie bleue", "Botella con una vela azul"},
|
||||
Text{"Bottle with Red Ice", "Flacon de Glace Rouge", "Botella de Hielo rojo"},
|
||||
Text{"Bottle with Nayru's Flame", "Flacon de flamme de Nayru", "Botella de llamas de Nayru"}};
|
||||
trickNameTable[0x92] = {
|
||||
trickNameTable[RG_BOTTLE_WITH_BUGS] = {
|
||||
Text{"Bottle with Baby Tektites", "Flacon de bébé Araknon", "Tektites en una botella"},
|
||||
Text{"Bottle with A Beetle", "Flacon avec un scarabée", "Botella con un escarabajo"},
|
||||
Text{"Bottle with Lanayru Ants", "Flacon de fourmis de Lanelle", "Celestarabajo embotellado"},
|
||||
Text{"Bottle with Insects", "Flacon de bibittes", "Saltabosques embotellados"},
|
||||
Text{"Bottle with a Golden Bee", "Flacon avec une abeille dorée", "Botella con una abeja dorada"}};
|
||||
trickNameTable[0x94] = {
|
||||
trickNameTable[RG_BOTTLE_WITH_POE] = {
|
||||
Text{"Bottle with Ghini", "Flacon avec Ghini", "Ghini en una botella"},
|
||||
Text{"Bottle with Reapling", "Flacon avec Âme Damnée", "Reapling en una botella"},
|
||||
Text{"Bottle with Imp Poe", "Flacon avec Spectre", "Espectro en una botella"},
|
||||
Text{"Bottle with Anti-Fairy", "Flacon avec Tetdoss", "Whisp en una botella"}};
|
||||
|
||||
trickNameTable[0x15] = {
|
||||
trickNameTable[RG_RUTOS_LETTER] = {
|
||||
Text{"Bottle with Maggie's Letter", "Flacon avec lettre de Maggy", "Carta de Dolores"},
|
||||
Text{"Bottle with Letter to Kafei", "Flacon avec lettre pour Kafei", "Carta para Kafei"},
|
||||
Text{"Bottle with Zelda's Letter", "Flacon avec Lettre de Zelda", "Carta náutica"}};
|
||||
trickNameTable[0x93] = {
|
||||
trickNameTable[RG_BOTTLE_WITH_BIG_POE] = {
|
||||
Text{"Bottle with Composer Brother", "Flacon avec un compositeur", "Hermana Poe embotellada"},
|
||||
Text{"Bottle with Jalhalla", "Flacon avec Jalhalla", "Yaihalla embotellado"},
|
||||
Text{"Bottle with Grim Repoe", "Flacon avec le Faucheur", "Bubble en una botella"}};
|
||||
|
||||
trickNameTable[0xC1] = {
|
||||
trickNameTable[RG_ZELDAS_LULLABY] = {
|
||||
Text{"Ballad of the Goddess", "Chant de la déesse", "Cántico de la Diosa"},
|
||||
Text{"Song of Healing", "Chant de l'apaisement", "Canción de curación"},
|
||||
Text{"Song of the Hero", "Chant du héros", "Canción del héroe"}};
|
||||
trickNameTable[0xC2] = {
|
||||
trickNameTable[RG_EPONAS_SONG] = {
|
||||
Text{"Song of Birds","Chant des oiseaux","Cantar del ave"},
|
||||
Text{"Song of Soaring", "Chant de l'envol", "Canción del viento"},
|
||||
Text{"Song of Horse", "Chant du cheval", "Chant du cheval"}};
|
||||
trickNameTable[0xC3] = {
|
||||
trickNameTable[RG_SARIAS_SONG] = {
|
||||
Text{"Mido's Song", "La chanson de Mido", "La canción de Mido"},
|
||||
Text{"Kass' Theme", "Le thème de Kass", "El tema de Kass"},
|
||||
Text{"Tune of Echoes", "Chant des Échos ", "Melodía del Eco "}};
|
||||
trickNameTable[0xC4] = {
|
||||
trickNameTable[RG_SUNS_SONG] = {
|
||||
Text{"Song of Passing", "Mambo de Manbo", "Melodía del transcurrir"},
|
||||
Text{"Command Melody", "Air du marionnettiste", "Cara al Sol"},
|
||||
Text{"Moon's Song", "La chanson de Moon", "La canción de la luna"}};
|
||||
trickNameTable[0xC5] = {
|
||||
trickNameTable[RG_SONG_OF_TIME] = {
|
||||
Text{"Song of Double Time", "Chant accéléré", "Canción del doble tiempo"},
|
||||
Text{"Inverted Song of Time", "Chant du temps inversé", "Canción del tiempo invertida"},
|
||||
Text{"Tune of Ages", "Chant du Temps", "Melodía del Tiempo"}};
|
||||
trickNameTable[0xC6] = {
|
||||
trickNameTable[RG_SONG_OF_STORMS] = {
|
||||
Text{"Ballad of Gales", "Requiem de la tornade", "Melodía del Tornado"},
|
||||
Text{"Frog's Song of Soul", "Rap des grenouilles", "Canción del alma de la rana"},
|
||||
Text{"Wind's Requiem", "Mélodie du vent", "Melodía del Viento"}};
|
||||
trickNameTable[0xBB] = {
|
||||
trickNameTable[RG_MINUET_OF_FOREST] = {
|
||||
Text{"Saria's Karaoke", "Karaoké de Saria", "Dueto del bosque"},
|
||||
Text{"Sonata of Awakening", "Sonate de l'éveil", "Sonata del despertar"},
|
||||
Text{"Wind God's Aria", "Hymne du dieu du vent", "Melodía del Espíritu del Viento"}};
|
||||
trickNameTable[0xBC] = {
|
||||
trickNameTable[RG_BOLERO_OF_FIRE] = {
|
||||
Text{"Darunia's Tango", "Tango de Darunia", "Coro del fuego"},
|
||||
Text{"Tune of Currents", "Chants des Flux", "Melodía de las Corrientes"},
|
||||
Text{"Goron Lullaby", "Berceuse des Gorons", "Nana goron"}};
|
||||
trickNameTable[0xBD] = {
|
||||
trickNameTable[RG_SERENADE_OF_WATER] = {
|
||||
Text{"Ruto's Blues", "Blues de Ruto", "Sonata del agua"},
|
||||
Text{"New Wave Bossa Nova", "Bossa-nova des flots", "Bossanova de las olas"},
|
||||
Text{"Manbo's Mambo", "Mambo de Manbo", "Mambo de Manbo"}};
|
||||
trickNameTable[0xBE] = {
|
||||
trickNameTable[RG_REQUIEM_OF_SPIRIT] = {
|
||||
Text{"Nabooru's Reggae", "Reggae de Nabooru", "Reggae del espíritu"},
|
||||
Text{"Elegy of Emptiness", "Hymne du vide", "Elegía al vacío"},
|
||||
Text{"Earth God's Lyric", "Hymne du dieu de la terre", "Melodía del Espíritu de la Tierra"}};
|
||||
trickNameTable[0xBF] = {
|
||||
trickNameTable[RG_NOCTURNE_OF_SHADOW] = {
|
||||
Text{"Impa's Death Metal", "Death métal d'Impa", "Diurno de la sombra"},
|
||||
Text{"Oath to Order", "Ode de l'appel", "Oda al orden"},
|
||||
Text{"Song of Discovery", "Chant des secrets", "Canto revelador"}};
|
||||
trickNameTable[0xC0] = {
|
||||
trickNameTable[RG_PRELUDE_OF_LIGHT] = {
|
||||
Text{"Rauru's Sing-Along", "Chansonnette de Rauru", "Predulio de luz"},
|
||||
Text{"Ballad of the Wind Fish", "Ballade sur Poisson-Rêve", "Balada del Piez Viento"},
|
||||
Text{"Song of Light", "Chant de la lumière", "Sonidos de la luz"}};
|
||||
|
||||
trickNameTable[0xCB] = {
|
||||
trickNameTable[RG_KOKIRI_EMERALD] = {
|
||||
Text{"Pendant of Courage", "Pendentif du courage", "Colgante del valor"},
|
||||
Text{"Farore's Pearl", "Perle de Farore", "Orbe de Farore"},
|
||||
Text{"Aquanine", "Smaragdine", "Yerbánida"},
|
||||
Text{"Farore's Emerald", "Émeraude de Farore", "Esmeralda de Farore"},
|
||||
Text{"Kokiri's Peridot", "Péridot Kokiri", "Ágata de los Kokiri"}};
|
||||
trickNameTable[0xCC] = {
|
||||
trickNameTable[RG_GORON_RUBY] = {
|
||||
Text{"Pendant of Power", "Pendentif de la force", "Colgante del poder"},
|
||||
Text{"Din's Pearl", "Perle de Din", "Orbe de Din"},
|
||||
Text{"Crimsonine", "Alzanine", "Bermellina"},
|
||||
Text{"Din's Ruby", "Rubis de Din", "Rubí de Din"},
|
||||
Text{"Goron's Garnet", "Grenat Goron", "Topacio de los Goron"}};
|
||||
trickNameTable[0xCD] = {
|
||||
trickNameTable[RG_ZORA_SAPPHIRE] = {
|
||||
Text{"Pendant of Wisdom", "Pendentif de la sagesse", "Colgante de la sabiduría"},
|
||||
Text{"Nayru's Pearl", "Perle de Nayru", "Orbe de Nayru"},
|
||||
Text{"Azurine", "Aquanine", "Azurina"},
|
||||
Text{"Nayru's Sapphire", "Saphir de Nayru", "Zafiro de Nayru"},
|
||||
Text{"Zora's Aquamarine", "Aquamarine Zora", "Lapislázuli de los Zora"}};
|
||||
trickNameTable[0xCE] = {
|
||||
trickNameTable[RG_FOREST_MEDALLION] = {
|
||||
Text{"Wind Medallion", "Médaillon du vent", "Medallón del Viento"},
|
||||
Text{"Wind Element", "Elément Vent", "Elemento de aire"},
|
||||
Text{"Saria's Medallion", "Médaillon de Saria", "Medallón de Saria"},
|
||||
Text{"Sign of Air", "Glyphe de l'air", "Glifo de aire"},
|
||||
Text{"Medallion of Forest", "Médaillon du Temple de la Forêt", "Medalla del Bosque"}};
|
||||
trickNameTable[0xCF] = {
|
||||
trickNameTable[RG_FIRE_MEDALLION] = {
|
||||
Text{"Fire Element", "Elément Feu", "Elemento de fuego"},
|
||||
Text{"Darunia's Medallion", "Médaillon de Darunia", "Medallón de Darunia"},
|
||||
Text{"Sign of Fire", "Glyphe de feu", "Glifo de fuego"},
|
||||
Text{"Medallion of Fire", "Médaillon du Temple du Feu", "Medalla del Fuego"}};
|
||||
trickNameTable[0xD0] = {
|
||||
trickNameTable[RG_WATER_MEDALLION] = {
|
||||
Text{"Water Element", "Elément Eau", "Elemento de agua"},
|
||||
Text{"Ice Medallion", "Médaillon de glace", "Medallón Helado"},
|
||||
Text{"Ruto's Medallion", "Médaillon de Ruto", "Medallón de Ruto"},
|
||||
Text{"Sign of Water", "Glyphe de l'eau", "Glifo de agua"},
|
||||
Text{"Medallion of Water", "Médaillon du Temple de l'Eau", "Medalla del Agua"}};
|
||||
trickNameTable[0xD1] = {
|
||||
trickNameTable[RG_SPIRIT_MEDALLION] = {
|
||||
Text{"Earth Element", "Elément Terre", "Elemento de tierra"},
|
||||
Text{"Nabooru's Medallion", "Médaillon de Nabooru", "Medallón de Nabooru"},
|
||||
Text{"Sign of Earth", "Glyphe de la Terre", "Glifo de la tierra"},
|
||||
Text{"Medallion of Spirit", "Médaillon du Temple de l'Esprit", "Medalla del Espíritu"}};
|
||||
trickNameTable[0xD2] = {
|
||||
trickNameTable[RG_SHADOW_MEDALLION] = {
|
||||
Text{"Fused Shadow", "Cristal d'ombre", "Sombra Fundida"},
|
||||
Text{"Impa's Medallion", "Médaillon d'Impa", "Medallón de Impa"},
|
||||
Text{"Sign of Illusion", "Glyphe de l'illusion", "Glifo de ilusión"},
|
||||
Text{"Medallion of Shadow", "Médaillon du Temple de l'Ombre", "Medalla de la Sombra"}};
|
||||
trickNameTable[0xD3] = {
|
||||
trickNameTable[RG_LIGHT_MEDALLION] = {
|
||||
Text{"Compass of Light", "Boussole de lumière", "Brújula de Luz"},
|
||||
Text{"Rauru's Medallion", "Médaillon de Rauru", "Medallón de Rauru"},
|
||||
Text{"Sign of Destiny", "Glyphe du destin", "Glifo del destino"},
|
||||
Text{"Medallion of Light", "Médaillon du temple de lumière", "Medalla de la Luz"}};
|
||||
|
||||
trickNameTable[GI_HEART] = {
|
||||
trickNameTable[RG_RECOVERY_HEART] = {
|
||||
Text{"Love", "Bisou", "Te amo"},
|
||||
Text{"Life", "Vie", "vida"},
|
||||
Text{"HP", "VP", "VP"}};
|
||||
trickNameTable[GI_RUPEE_GREEN] = {
|
||||
trickNameTable[RG_GREEN_RUPEE] = {
|
||||
Text{"False Greg", "Faux Greg", "Falso Greg"},
|
||||
Text{"One Ruby", "Un rubis", "Un rubí"},
|
||||
Text{"Rupoor (1)", "Roupir (1)", "Rupobre (1)"},
|
||||
Text{"One Rupee", "Un rubis", "Guaraní hyliano"},
|
||||
Text{"Rupee (1)", "Rubis (1)", "Peso hyliano"}};
|
||||
trickNameTable[GI_RUPEE_BLUE] = {
|
||||
trickNameTable[RG_BLUE_RUPEE] = {
|
||||
Text{"Blupee", "Bleubi", "Azupia"},
|
||||
Text{"Five Rubies", "Cinq Rubys", "Cinco rubíes"},
|
||||
Text{"Five Rupees", "Cinq rubis", "Bolívar hyliano"},
|
||||
Text{"Rupee (5)", "Rubis (5)", "Peso hyliano"},
|
||||
Text{"Rupoor (5)", "Roupir (5)", "Rupobre (5)"}};
|
||||
trickNameTable[GI_RUPEE_RED] = {
|
||||
trickNameTable[RG_RED_RUPEE] = {
|
||||
Text{"Big 20", "Grand 20", "Los 20 grandes"},
|
||||
Text{"Twenty Rubies", "vingt rubis", "Veinte rubíes"},
|
||||
Text{"Rupoor (20)", "Roupir (20)", "Rupobre (20)"},
|
||||
Text{"Twenty Rupees", "Vingt rubis", "Colon hyliano"},
|
||||
Text{"Rupee (20)", "Rubis (20)", "Peso hyliano"}};
|
||||
trickNameTable[GI_RUPEE_PURPLE] = {
|
||||
trickNameTable[RG_PURPLE_RUPEE] = {
|
||||
Text{"Purpee", "pourbi", "morupiua"},
|
||||
Text{"Fifty Rubies", "cinquante rubis", "Cincuenta rubíes"},
|
||||
Text{"Rupoor (50)", "Roupir (50)", "Rupobre (50)"},
|
||||
Text{"Fifty Rupees", "Cinquante rubis", "Balboa hyliano"},
|
||||
Text{"Rupee (50)", "Rubis (50)", "Peso hyliano"}};
|
||||
trickNameTable[GI_RUPEE_GOLD] = {
|
||||
trickNameTable[RG_HUGE_RUPEE] = {
|
||||
Text{"Hugo", "Or Rubi", "Oro Rubi"},
|
||||
Text{"Two Hundred Rubies", "deux cents rubis", "Doscientos rubíes"},
|
||||
Text{"Diamond", "Diamant", "Diamante"},
|
||||
Text{"Huge Ruby", "Énorme rubis", "Rubi gigante"},
|
||||
Text{"Two Hundred Rupees", "Deux cent rubis", "Euro hyliano"},
|
||||
Text{"Rupee (200)", "Rubis (200)", "Dólar hyliano"}};
|
||||
trickNameTable[GI_HEART_PIECE] = {
|
||||
trickNameTable[RG_PIECE_OF_HEART] = {
|
||||
Text{"Pizza Heart", "Fromage de cœur", "Pieza de Chorizo"},
|
||||
Text{"Little Bit Of Love", "Un peu d'amour", "Un poco de amor"},
|
||||
Text{"Rare Peach Stone", "Pierre de pêche rare", "Pierre de pêche rare"}};
|
||||
trickNameTable[GI_HEART_CONTAINER_2] = {
|
||||
trickNameTable[RG_HEART_CONTAINER] = {
|
||||
Text{"Crystal Heart", "Cœur de cristal", "Corazón de cristal"},
|
||||
Text{"Life Heart", "Cœur de vie", "Vida Corazón"},
|
||||
Text{"Lots of Love", "Beaucoup d'amour", "Mucho amor"}};
|
||||
trickNameTable[0xDF] = {
|
||||
trickNameTable[RG_TRIFORCE_PIECE] = {
|
||||
Text{"Piece of Cheese", "Morceau de Fromage", "Piece of Cheese"},
|
||||
Text{"Triforce Shard", "Éclat de Triforce", "Triforce Shard"},
|
||||
Text{"Shiny Rock", "Caiiloux Brillant", "Shiny Rock"}};
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#include "spoiler_log.hpp"
|
||||
|
||||
#include "dungeon.hpp"
|
||||
#include "../dungeon.h"
|
||||
#include "../static_data.h"
|
||||
#include "../context.h"
|
||||
#include "entrance.hpp"
|
||||
#include "../entrance.h"
|
||||
#include "random.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "trial.hpp"
|
||||
#include "../trial.h"
|
||||
#include "tinyxml2.h"
|
||||
#include "utils.hpp"
|
||||
#include "shops.hpp"
|
||||
@@ -33,6 +32,7 @@
|
||||
#include <Context.h>
|
||||
|
||||
using json = nlohmann::ordered_json;
|
||||
using namespace Rando;
|
||||
|
||||
json jsonData;
|
||||
std::map<RandomizerHintTextKey, Rando::ItemLocation*> hintedLocations;
|
||||
@@ -48,14 +48,15 @@ std::string placementtxt;
|
||||
static SpoilerData spoilerData;
|
||||
|
||||
void GenerateHash() {
|
||||
std::string hash = Settings::hash;
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
std::string hash = ctx->GetSettings()->GetHash();
|
||||
// adds leading 0s to the hash string if it has less than 10 digits.
|
||||
while (hash.length() < 10) {
|
||||
hash = "0" + hash;
|
||||
}
|
||||
for (size_t i = 0, j = 0; i < Settings::hashIconIndexes.size(); i++, j += 2) {
|
||||
for (size_t i = 0, j = 0; i < ctx->hashIconIndexes.size(); i++, j += 2) {
|
||||
int number = std::stoi(hash.substr(j, 2));
|
||||
Settings::hashIconIndexes[i] = number;
|
||||
ctx->hashIconIndexes[i] = number;
|
||||
}
|
||||
|
||||
// Clear out spoiler log data here, in case we aren't going to re-generate it
|
||||
@@ -114,26 +115,26 @@ void WriteIngameSpoilerLog() {
|
||||
// continue;
|
||||
// }
|
||||
// Cows
|
||||
if (!Settings::ShuffleCows && loc->IsCategory(Category::cCow)) {
|
||||
if (!ctx->GetOption(RSK_SHUFFLE_COWS) && loc->IsCategory(Category::cCow)) {
|
||||
continue;
|
||||
}
|
||||
// Merchants
|
||||
else if (Settings::ShuffleMerchants.Is(SHUFFLEMERCHANTS_OFF) && loc->IsCategory(Category::cMerchant)) {
|
||||
else if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_OFF) && loc->IsCategory(Category::cMerchant)) {
|
||||
continue;
|
||||
}
|
||||
// Adult Trade
|
||||
else if (!Settings::ShuffleAdultTradeQuest && loc->IsCategory(Category::cAdultTrade)) {
|
||||
else if (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && loc->IsCategory(Category::cAdultTrade)) {
|
||||
continue;
|
||||
}
|
||||
// Chest Minigame
|
||||
else if (Settings::ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_OFF) &&
|
||||
else if (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_GENERIC_OFF) &&
|
||||
loc->IsCategory(Category::cChestMinigame)) {
|
||||
continue;
|
||||
}
|
||||
// Gerudo Fortress
|
||||
else if ((Settings::GerudoFortress.Is(GERUDOFORTRESS_OPEN) &&
|
||||
else if ((ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_NORMAL) &&
|
||||
(loc->IsCategory(Category::cVanillaGFSmallKey) || loc->GetHintKey() == RHT_GF_GERUDO_MEMBERSHIP_CARD)) ||
|
||||
(Settings::GerudoFortress.Is(GERUDOFORTRESS_FAST) && loc->IsCategory(Category::cVanillaGFSmallKey) &&
|
||||
(ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_FAST) && loc->IsCategory(Category::cVanillaGFSmallKey) &&
|
||||
loc->GetHintKey() != RHT_GF_NORTH_F1_CARPENTER)) {
|
||||
continue;
|
||||
}
|
||||
@@ -186,7 +187,7 @@ void WriteIngameSpoilerLog() {
|
||||
}
|
||||
// Shops
|
||||
else if (loc->IsShop()) {
|
||||
if (Settings::Shopsanity.Is(SHOPSANITY_OFF)) {
|
||||
if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF)) {
|
||||
spoilerData.ItemLocations[spoilerItemIndex].RevealType = REVEALTYPE_ALWAYS;
|
||||
} else {
|
||||
spoilerData.ItemLocations[spoilerItemIndex].RevealType = REVEALTYPE_SCENE;
|
||||
@@ -199,14 +200,14 @@ void WriteIngameSpoilerLog() {
|
||||
}
|
||||
// Gold Skulltulas
|
||||
else if (loc->IsCategory(Category::cSkulltula) &&
|
||||
((Settings::Tokensanity.Is(TOKENSANITY_OFF)) ||
|
||||
(Settings::Tokensanity.Is(TOKENSANITY_DUNGEONS) && !loc->IsDungeon()) ||
|
||||
(Settings::Tokensanity.Is(TOKENSANITY_OVERWORLD) && loc->IsDungeon()))) {
|
||||
((ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF)) ||
|
||||
(ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_DUNGEONS) && !loc->IsDungeon()) ||
|
||||
(ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OVERWORLD) && loc->IsDungeon()))) {
|
||||
spoilerData.ItemLocations[spoilerItemIndex].RevealType = REVEALTYPE_ALWAYS;
|
||||
}
|
||||
// Deku Scrubs
|
||||
else if (loc->IsCategory(Category::cDekuScrub) && !loc->IsCategory(Category::cDekuScrubUpgrades) &&
|
||||
Settings::Scrubsanity.Is(SCRUBSANITY_OFF)) {
|
||||
ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF)) {
|
||||
spoilerData.ItemLocations[spoilerItemIndex].CollectType = COLLECTTYPE_REPEATABLE;
|
||||
spoilerData.ItemLocations[spoilerItemIndex].RevealType = REVEALTYPE_ALWAYS;
|
||||
}
|
||||
@@ -226,7 +227,7 @@ void WriteIngameSpoilerLog() {
|
||||
}
|
||||
spoilerData.ItemLocationsCount = spoilerItemIndex;
|
||||
|
||||
if (Settings::IngameSpoilers) {
|
||||
if (/*Settings::IngameSpoilers TODO: Remove: don't think we have any need for this*/ false) {
|
||||
bool playthroughItemNotFound = false;
|
||||
// Write playthrough data to in-game spoiler log
|
||||
if (!spoilerOutOfSpace) {
|
||||
@@ -357,76 +358,47 @@ static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance)
|
||||
|
||||
// Writes the settings (without excluded locations, starting inventory and tricks) to the spoilerLog document.
|
||||
static void WriteSettings(const bool printAll = false) {
|
||||
// auto parentNode = spoilerLog.NewElement("settings");
|
||||
|
||||
std::vector<Menu*> allMenus = Settings::GetAllOptionMenus();
|
||||
|
||||
for (const Menu* menu : allMenus) {
|
||||
if (menu->name == "Item Usability Settings" ||
|
||||
menu->name == "Multiplayer Settings") continue;
|
||||
|
||||
if (menu->name == "Timesaver Settings") {
|
||||
for (const Option* setting : *menu->settingsList) {
|
||||
if (setting->GetName() == "Big Poe Target Count" ||
|
||||
setting->GetName() == "Cuccos to return" ||
|
||||
setting->GetName() == "Skip Epona Race" ||
|
||||
setting->GetName() == "Skip Tower Escape" ||
|
||||
setting->GetName() == "Skip Child Stealth" ||
|
||||
setting->GetName() == "Complete Mask Quest" ||
|
||||
setting->GetName() == "Skip Scarecrow's Song" ||
|
||||
setting->GetName() == "Enable Glitch-Useful Cutscenes") {
|
||||
std::string settingName = menu->name + ":" + setting->GetName();
|
||||
jsonData["settings"][settingName] = setting->GetSelectedOptionText();
|
||||
// auto parentNode = spoilerLog.NewElement("settings");
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
auto allOptionGroups = ctx->GetSettings()->GetOptionGroups();
|
||||
for (const Rando::OptionGroup& optionGroup : allOptionGroups) {
|
||||
if (optionGroup.GetName() == "Timesaver Settings") {
|
||||
for (const Rando::Option* option : optionGroup.GetOptions()) {
|
||||
if (option->GetName() == "Big Poe Target Count" || option->GetName() == "Cuccos to return" ||
|
||||
option->GetName() == "Skip Epona Race" || option->GetName() == "Skip Tower Escape" ||
|
||||
option->GetName() == "Skip Child Stealth" || option->GetName() == "Complete Mask Quest" ||
|
||||
option->GetName() == "Skip Scarecrow's Song" ||
|
||||
option->GetName() == "Enable Glitch-Useful Cutscenes") {
|
||||
std::string settingName = optionGroup.GetName() + ":" + option->GetName();
|
||||
jsonData["settings"][settingName] = option->GetSelectedOptionText();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (optionGroup.GetContainsType() == Rando::OptionGroupType::DEFAULT && optionGroup.PrintInSpoiler()) {
|
||||
for (const Rando::Option* option : optionGroup.GetOptions()) {
|
||||
std::string settingName = optionGroup.GetName() + ":" + option->GetName();
|
||||
jsonData["settings"][settingName] = option->GetSelectedOptionText();
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//This is a menu of settings, write them
|
||||
if (menu->mode == OPTION_SUB_MENU && menu->printInSpoiler) {
|
||||
for (const Option* setting : *menu->settingsList) {
|
||||
std::string settingName = menu->name + ":" + setting->GetName();
|
||||
jsonData["settings"][settingName] = setting->GetSelectedOptionText();
|
||||
}
|
||||
// spoilerLog.RootElement()->InsertEndChild(parentNode);
|
||||
|
||||
|
||||
// for (const Option* setting : *menu->settingsList) {
|
||||
// if (printAll || (!setting->IsHidden() && setting->IsCategory(OptionCategory::Setting))) {
|
||||
// auto node = parentNode->InsertNewChildElement("setting");
|
||||
// node->SetAttribute("name", RemoveLineBreaks(setting->GetName()).c_str());
|
||||
// node->SetText(setting->GetSelectedOptionText().c_str());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// 3drando doesn't have a "skip child zelda" setting, manually add it to the spoilerfile
|
||||
jsonData["settings"]["Skip Child Zelda"] = Settings::skipChildZelda;
|
||||
|
||||
// 3drando uses an MQ dungeon count of 13 to mean random, manually add that to the spoilerfile as a bool
|
||||
if (Settings::MQDungeonCount.GetSelectedOptionIndex() == 0) {
|
||||
jsonData["settings"]["World Settings:MQ Dungeons"] = "None";
|
||||
} else if (Settings::MQDungeonCount.GetSelectedOptionIndex() == 13) {
|
||||
jsonData["settings"]["World Settings:MQ Dungeons"] = "Random Number";
|
||||
} else {
|
||||
jsonData["settings"]["World Settings:MQ Dungeons"] = "Set Number";
|
||||
}
|
||||
|
||||
// spoilerLog.RootElement()->InsertEndChild(parentNode);
|
||||
|
||||
// for (const uint32_t key : allLocations) {
|
||||
// ItemLocation* location = GetLocation(key);
|
||||
// settingsJsonData["locations"][location->GetName()] = location->GetPlacedItemName().english;
|
||||
// }
|
||||
// for (const uint32_t key : allLocations) {
|
||||
// ItemLocation* location = GetLocation(key);
|
||||
// settingsJsonData["locations"][location->GetName()] = location->GetPlacedItemName().english;
|
||||
// }
|
||||
}
|
||||
|
||||
// Writes the excluded locations to the spoiler log, if there are any.
|
||||
static void WriteExcludedLocations() {
|
||||
// auto parentNode = spoilerLog.NewElement("excluded-locations");
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
|
||||
for (size_t i = 1; i < Settings::excludeLocationsOptionsVector.size(); i++) {
|
||||
for (const auto& location : Settings::excludeLocationsOptionsVector[i]) {
|
||||
if (location->GetSelectedOptionIndex() == INCLUDE) {
|
||||
for (size_t i = 1; i < ctx->GetSettings()->GetExcludeLocationsOptions().size(); i++) {
|
||||
for (const auto& location : ctx->GetSettings()->GetExcludeLocationsOptions()[i]) {
|
||||
if (location->GetSelectedOptionIndex() == RO_LOCATION_INCLUDE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -445,61 +417,24 @@ static void WriteExcludedLocations() {
|
||||
|
||||
// Writes the starting inventory to the spoiler log, if there is any.
|
||||
static void WriteStartingInventory() {
|
||||
std::vector<std::vector<Option *>*> startingInventoryOptions = {
|
||||
&Settings::startingItemsOptions,
|
||||
&Settings::startingSongsOptions,
|
||||
&Settings::startingEquipmentOptions,
|
||||
&Settings::startingStonesMedallionsOptions,
|
||||
&Settings::startingOthersOptions
|
||||
};
|
||||
|
||||
for (std::vector<Option*>* menu : startingInventoryOptions) {
|
||||
for (size_t i = 0; i < menu->size(); ++i) {
|
||||
const auto setting = menu->at(i);
|
||||
// Starting Songs
|
||||
if (setting->GetName() == "Start with Zelda's Lullaby" ||
|
||||
setting->GetName() == "Start with Epona's Song" ||
|
||||
setting->GetName() == "Start with Saria's Song" ||
|
||||
setting->GetName() == "Start with Sun's Song" ||
|
||||
setting->GetName() == "Start with Song of Time" ||
|
||||
setting->GetName() == "Start with Song of Storms" ||
|
||||
setting->GetName() == "Start with Minuet of Forest" ||
|
||||
setting->GetName() == "Start with Bolero of Fire" ||
|
||||
setting->GetName() == "Start with Serenade of Water" ||
|
||||
setting->GetName() == "Start with Requiem of Spirit" ||
|
||||
setting->GetName() == "Start with Nocturne of Shadow" ||
|
||||
setting->GetName() == "Start with Prelude of Light") {
|
||||
jsonData["settings"][setting->GetName()] = setting->GetSelectedOptionText();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (std::vector<Option *>* menu : startingInventoryOptions) {
|
||||
for (size_t i = 0; i < menu->size(); ++i) {
|
||||
const auto setting = menu->at(i);
|
||||
|
||||
// we need to write these every time because we're not clearing jsondata, so
|
||||
// the default logic of only writing it when we aren't using the default value
|
||||
// doesn't work, and because it'd be bad to set every single possible starting
|
||||
// inventory item as "false" in the json, we're just going to check
|
||||
// to see if the name is one of the 3 we're using rn
|
||||
if (setting->GetName() == "Start with Consumables" ||
|
||||
setting->GetName() == "Start with Max Rupees" ||
|
||||
setting->GetName() == "Gold Skulltula Tokens" ||
|
||||
setting->GetName() == "Start with Fairy Ocarina" ||
|
||||
setting->GetName() == "Start with Kokiri Sword" ||
|
||||
setting->GetName() == "Start with Deku Shield") {
|
||||
jsonData["settings"][setting->GetName()] = setting->GetSelectedOptionText();
|
||||
}
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
const Rando::OptionGroup& optionGroup = ctx->GetSettings()->GetOptionGroup(RSG_STARTING_INVENTORY);
|
||||
for (const Rando::OptionGroup* subGroup : optionGroup.GetSubGroups()) {
|
||||
if (subGroup->GetContainsType() == Rando::OptionGroupType::DEFAULT) {
|
||||
for (const Rando::Option* option : subGroup->GetOptions()) {
|
||||
jsonData["settings"][option->GetName()] = option->GetSelectedOptionText();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Writes the enabled tricks to the spoiler log, if there are any.
|
||||
static void WriteEnabledTricks(tinyxml2::XMLDocument& spoilerLog) {
|
||||
//auto parentNode = spoilerLog.NewElement("enabled-tricks");
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
|
||||
for (const auto& setting : Settings::trickOptions) {
|
||||
if (setting->GetSelectedOptionIndex() != TRICK_ENABLED/* || !setting->IsCategory(OptionCategory::Setting)*/) {
|
||||
for (const auto& setting : ctx->GetSettings()->GetOptionGroup(RSG_TRICKS).GetOptions()) {
|
||||
if (setting->GetSelectedOptionIndex() != RO_GENERIC_ON/* || !setting->IsCategory(OptionCategory::Setting)*/) {
|
||||
continue;
|
||||
}
|
||||
jsonData["enabledTricks"].push_back(RemoveLineBreaks(RandomizerTricks::GetRTName((RandomizerTrick)std::stoi(setting->GetName()))).c_str());
|
||||
@@ -513,36 +448,38 @@ static void WriteEnabledTricks(tinyxml2::XMLDocument& spoilerLog) {
|
||||
}
|
||||
|
||||
// Writes the enabled glitches to the spoiler log, if there are any.
|
||||
static void WriteEnabledGlitches(tinyxml2::XMLDocument& spoilerLog) {
|
||||
auto parentNode = spoilerLog.NewElement("enabled-glitches");
|
||||
// TODO: Implement Glitches
|
||||
// static void WriteEnabledGlitches(tinyxml2::XMLDocument& spoilerLog) {
|
||||
// auto parentNode = spoilerLog.NewElement("enabled-glitches");
|
||||
|
||||
for (const auto& setting : Settings::glitchCategories) {
|
||||
if (setting->Value<uint8_t>() == 0) {
|
||||
continue;
|
||||
}
|
||||
// for (const auto& setting : Settings::glitchCategories) {
|
||||
// if (setting->Value<uint8_t>() == 0) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
auto node = parentNode->InsertNewChildElement("glitch-category");
|
||||
node->SetAttribute("name", setting->GetName().c_str());
|
||||
node->SetText(setting->GetSelectedOptionText().c_str());
|
||||
}
|
||||
// auto node = parentNode->InsertNewChildElement("glitch-category");
|
||||
// node->SetAttribute("name", setting->GetName().c_str());
|
||||
// node->SetText(setting->GetSelectedOptionText().c_str());
|
||||
// }
|
||||
|
||||
for (const auto& setting : Settings::miscGlitches) {
|
||||
if (!setting->Value<bool>()) {
|
||||
continue;
|
||||
}
|
||||
// for (const auto& setting : Settings::miscGlitches) {
|
||||
// if (!setting->Value<bool>()) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
auto node = parentNode->InsertNewChildElement("misc-glitch");
|
||||
node->SetAttribute("name", RemoveLineBreaks(setting->GetName()).c_str());
|
||||
}
|
||||
// auto node = parentNode->InsertNewChildElement("misc-glitch");
|
||||
// node->SetAttribute("name", RemoveLineBreaks(setting->GetName()).c_str());
|
||||
// }
|
||||
|
||||
if (!parentNode->NoChildren()) {
|
||||
spoilerLog.RootElement()->InsertEndChild(parentNode);
|
||||
}
|
||||
}
|
||||
// if (!parentNode->NoChildren()) {
|
||||
// spoilerLog.RootElement()->InsertEndChild(parentNode);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Writes the Master Quest dungeons to the spoiler log, if there are any.
|
||||
static void WriteMasterQuestDungeons(tinyxml2::XMLDocument& spoilerLog) {
|
||||
for (const auto* dungeon : Dungeon::dungeonList) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (const auto* dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
std::string dungeonName;
|
||||
if (dungeon->IsVanilla()) {
|
||||
continue;
|
||||
@@ -553,7 +490,8 @@ static void WriteMasterQuestDungeons(tinyxml2::XMLDocument& spoilerLog) {
|
||||
|
||||
// Writes the required trials to the spoiler log, if there are any.
|
||||
static void WriteRequiredTrials() {
|
||||
for (const auto& trial : Trial::trialList) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (const auto& trial : ctx->GetTrials()->GetTrialList()) {
|
||||
if (trial->IsRequired()) {
|
||||
std::string trialName;
|
||||
switch (gSaveContext.language) {
|
||||
@@ -590,13 +528,14 @@ static void WritePlaythrough() {
|
||||
|
||||
//Write the randomized entrance playthrough to the spoiler log, if applicable
|
||||
static void WriteShuffledEntrances() {
|
||||
for (uint32_t i = 0; i < playthroughEntrances.size(); ++i) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (uint32_t i = 0; i < ctx->GetEntranceShuffler()->playthroughEntrances.size(); ++i) {
|
||||
auto sphereNum = std::to_string(i);
|
||||
std::string sphereString = "sphere ";
|
||||
if (i < 10) sphereString += "0";
|
||||
sphereString += sphereNum;
|
||||
for (Entrance* entrance : playthroughEntrances[i]) {
|
||||
WriteShuffledEntrance(sphereString, entrance);
|
||||
for (Entrance* entrance : ctx->GetEntranceShuffler()->playthroughEntrances[i]) {
|
||||
WriteShuffledEntrance(sphereString, entrance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -673,6 +612,7 @@ Rando::ItemLocation* GetItemLocation(RandomizerGet item) {
|
||||
|
||||
// Writes the hints to the spoiler log, if they are enabled.
|
||||
static void WriteHints(int language) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
std::string unformattedGanonText;
|
||||
std::string unformattedGanonHintText;
|
||||
std::string unformattedDampesText;
|
||||
@@ -690,7 +630,7 @@ static void WriteHints(int language) {
|
||||
unformattedSheikText = GetSheikHintText().GetEnglish();
|
||||
unformattedSariaText = GetSariaHintText().GetEnglish();
|
||||
|
||||
if (Settings::ShuffleWarpSongs){
|
||||
if (ctx->GetOption(RSK_SHUFFLE_WARP_SONGS)){
|
||||
jsonData["warpMinuetText"] = GetWarpMinuetText().GetEnglish();
|
||||
jsonData["warpBoleroText"] = GetWarpBoleroText().GetEnglish();
|
||||
jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetEnglish();
|
||||
@@ -709,7 +649,7 @@ static void WriteHints(int language) {
|
||||
unformattedSheikText = GetSheikHintText().GetFrench();
|
||||
unformattedSariaText = GetSariaHintText().GetFrench();
|
||||
|
||||
if (Settings::ShuffleWarpSongs){
|
||||
if (ctx->GetOption(RSK_SHUFFLE_WARP_SONGS)){
|
||||
jsonData["warpMinuetText"] = GetWarpMinuetText().GetFrench();
|
||||
jsonData["warpBoleroText"] = GetWarpBoleroText().GetFrench();
|
||||
jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetFrench();
|
||||
@@ -762,48 +702,51 @@ static void WriteHints(int language) {
|
||||
std::string sariaText = AutoFormatHintTextString(unformattedSariaText);
|
||||
|
||||
jsonData["ganonText"] = ganonText;
|
||||
if (Settings::LightArrowHintText){
|
||||
if (ctx->GetOption(RSK_LIGHT_ARROWS_HINT)){
|
||||
jsonData["ganonHintText"] = ganonHintText;
|
||||
jsonData["lightArrowHintLoc"] = GetLightArrowHintLoc();
|
||||
jsonData["lightArrowRegion"] = ctx->GetHint(RH_GANONDORF_HINT)->GetHintedRegion();
|
||||
jsonData["masterSwordHintLoc"] = GetMasterSwordHintLoc();
|
||||
if (!Settings::GanonsTrialsCount.Is(0)){
|
||||
jsonData["sheikText"] = sheikText;
|
||||
if (!ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) {
|
||||
jsonData["sheikText"] = sheikText;
|
||||
}
|
||||
}
|
||||
if (Settings::DampeHintText){
|
||||
if (ctx->GetOption(RSK_DAMPES_DIARY_HINT)){
|
||||
jsonData["dampeText"] = dampesText;
|
||||
jsonData["dampeHintLoc"] = GetDampeHintLoc();
|
||||
jsonData["dampeRegion"] = ctx->GetHint(RH_DAMPES_DIARY)->GetHintedRegion();
|
||||
}
|
||||
if (Settings::GregHintText){
|
||||
if (ctx->GetOption(RSK_GREG_HINT)){
|
||||
jsonData["gregText"] = gregText;
|
||||
jsonData["gregLoc"] = GetGregHintLoc();
|
||||
jsonData["gregRegion"] = ctx->GetHint(RH_GREG_RUPEE)->GetHintedRegion();
|
||||
}
|
||||
if (Settings::SariaHintText){
|
||||
if (ctx->GetOption(RSK_SARIA_HINT)){
|
||||
jsonData["sariaText"] = sariaText;
|
||||
jsonData["sariaHintLoc"] = GetSariaHintLoc();
|
||||
jsonData["sariaRegion"] = ctx->GetHint(RH_SARIA)->GetHintedRegion();
|
||||
}
|
||||
|
||||
if (Settings::GossipStoneHints.Is(HINTS_NO_HINTS)) {
|
||||
if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NONE)) {
|
||||
return;
|
||||
}
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (const RandomizerCheck key : Rando::StaticData::gossipStoneLocations) {
|
||||
Rando::Hint* hint = ctx->GetHint((RandomizerHintKey)(key - RC_DMC_GOSSIP_STONE + 1));
|
||||
Rando::Hint* hint = ctx->GetHint((RandomizerHintKey)(key - RC_COLOSSUS_GOSSIP_STONE + 1));
|
||||
Rando::ItemLocation* hintedLocation = ctx->GetItemLocation(hint->GetHintedLocation());
|
||||
std::string unformattedHintTextString;
|
||||
std::string hintTextString;
|
||||
switch (language) {
|
||||
case 0:
|
||||
default:
|
||||
unformattedHintTextString = hint->GetText().GetEnglish();
|
||||
hintTextString = hint->GetText().GetEnglish();
|
||||
break;
|
||||
case 2:
|
||||
unformattedHintTextString = hint->GetText().GetFrench();
|
||||
hintTextString = hint->GetText().GetFrench();
|
||||
break;
|
||||
}
|
||||
|
||||
HintType hintType = hint->GetHintType();
|
||||
|
||||
std::string textStr = AutoFormatHintTextString(unformattedHintTextString);
|
||||
std::string textStr = hintTextString;
|
||||
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["hint"] = textStr;
|
||||
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["type"] = hintTypeNames[(int)hintType];
|
||||
if ((hintType >= HINT_TYPE_ALWAYS && hintType < HINT_TYPE_JUNK) || hintType == HINT_TYPE_WOTH) {
|
||||
@@ -837,8 +780,7 @@ static void WriteAllLocations(int language) {
|
||||
|
||||
// If it's a simple item (not an ice trap, doesn't have a price)
|
||||
// just add the name of the item and move on
|
||||
if (!location->HasScrubsanityPrice() &&
|
||||
!location->HasShopsanityPrice() &&
|
||||
if (!location->HasCustomPrice() &&
|
||||
location->GetPlacedRandomizerGet() != RG_ICE_TRAP) {
|
||||
|
||||
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()] = placedItemName;
|
||||
@@ -848,7 +790,7 @@ static void WriteAllLocations(int language) {
|
||||
// We're dealing with a complex item, build out the json object for it
|
||||
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["item"] = placedItemName;
|
||||
|
||||
if (location->HasScrubsanityPrice() || location->HasShopsanityPrice()) {
|
||||
if (location->HasCustomPrice()) {
|
||||
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["price"] =
|
||||
location->GetPrice();
|
||||
}
|
||||
@@ -861,15 +803,15 @@ static void WriteAllLocations(int language) {
|
||||
case 0:
|
||||
default:
|
||||
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["model"] =
|
||||
Rando::StaticData::ItemFromGIID(ctx->iceTrapModels[location->GetRandomizerCheck()]).GetName().english;
|
||||
Rando::StaticData::RetrieveItem(ctx->overrides[location->GetRandomizerCheck()].LooksLike()).GetName().english;
|
||||
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["trickName"] =
|
||||
GetIceTrapName(ctx->iceTrapModels[location->GetRandomizerCheck()]).english;
|
||||
ctx->overrides[location->GetRandomizerCheck()].GetTrickName().english;
|
||||
break;
|
||||
case 2:
|
||||
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["model"] =
|
||||
Rando::StaticData::ItemFromGIID(ctx->iceTrapModels[location->GetRandomizerCheck()]).GetName().french;
|
||||
Rando::StaticData::RetrieveItem(ctx->overrides[location->GetRandomizerCheck()].LooksLike()).GetName().french;
|
||||
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["trickName"] =
|
||||
GetIceTrapName(ctx->iceTrapModels[location->GetRandomizerCheck()]).french;
|
||||
ctx->overrides[location->GetRandomizerCheck()].GetTrickName().french;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -877,6 +819,7 @@ static void WriteAllLocations(int language) {
|
||||
}
|
||||
|
||||
const char* SpoilerLog_Write(int language) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
auto spoilerLog = tinyxml2::XMLDocument(false);
|
||||
spoilerLog.InsertEndChild(spoilerLog.NewDeclaration());
|
||||
|
||||
@@ -886,12 +829,12 @@ const char* SpoilerLog_Write(int language) {
|
||||
jsonData.clear();
|
||||
|
||||
jsonData["version"] = (char*) gBuildVersion;
|
||||
jsonData["seed"] = Settings::seedString;
|
||||
jsonData["finalSeed"] = Settings::seed;
|
||||
jsonData["seed"] = ctx->GetSettings()->GetSeedString();
|
||||
jsonData["finalSeed"] = ctx->GetSettings()->GetSeed();
|
||||
|
||||
// Write Hash
|
||||
int index = 0;
|
||||
for (uint8_t seed_value : Settings::hashIconIndexes) {
|
||||
for (uint8_t seed_value : ctx->hashIconIndexes) {
|
||||
jsonData["file_hash"][index] = seed_value;
|
||||
index++;
|
||||
}
|
||||
@@ -908,7 +851,6 @@ const char* SpoilerLog_Write(int language) {
|
||||
WritePlaythrough();
|
||||
//WriteWayOfTheHeroLocation(spoilerLog);
|
||||
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
ctx->playthroughLocations.clear();
|
||||
ctx->playthroughBeatable = false;
|
||||
ctx->wothLocations.clear();
|
||||
@@ -923,14 +865,14 @@ const char* SpoilerLog_Write(int language) {
|
||||
|
||||
std::string jsonString = jsonData.dump(4);
|
||||
std::ostringstream fileNameStream;
|
||||
for (int i = 0; i < Settings::hashIconIndexes.size(); i ++) {
|
||||
for (int i = 0; i < ctx->hashIconIndexes.size(); i ++) {
|
||||
if (i) {
|
||||
fileNameStream << '-';
|
||||
}
|
||||
if (Settings::hashIconIndexes[i] < 10) {
|
||||
if (ctx->hashIconIndexes[i] < 10) {
|
||||
fileNameStream << '0';
|
||||
}
|
||||
fileNameStream << std::to_string(Settings::hashIconIndexes[i]);
|
||||
fileNameStream << std::to_string(ctx->hashIconIndexes[i]);
|
||||
}
|
||||
std::string fileName = fileNameStream.str();
|
||||
std::ofstream jsonFile(LUS::Context::GetPathRelativeToAppDirectory(
|
||||
@@ -960,14 +902,15 @@ bool PlacementLog_Write() {
|
||||
auto rootNode = placementLog.NewElement("placement-log");
|
||||
placementLog.InsertEndChild(rootNode);
|
||||
|
||||
rootNode->SetAttribute("version", Settings::version.c_str());
|
||||
rootNode->SetAttribute("seed", Settings::seed);
|
||||
// rootNode->SetAttribute("version", Settings::version.c_str());
|
||||
// rootNode->SetAttribute("seed", Settings::seed);
|
||||
// TODO: Do we even use this?
|
||||
|
||||
// WriteSettings(placementLog, true); // Include hidden settings.
|
||||
// WriteExcludedLocations(placementLog);
|
||||
// WriteStartingInventory(placementLog);
|
||||
WriteEnabledTricks(placementLog);
|
||||
WriteEnabledGlitches(placementLog);
|
||||
//WriteEnabledGlitches(placementLog);
|
||||
WriteMasterQuestDungeons(placementLog);
|
||||
//WriteRequiredTrials(placementLog);
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#include "starting_inventory.hpp"
|
||||
|
||||
#include "dungeon.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "../dungeon.h"
|
||||
#include "../context.h"
|
||||
#include "pool_functions.hpp"
|
||||
#include "soh/Enhancements/randomizer/static_data.h"
|
||||
|
||||
using namespace Settings;
|
||||
using namespace Dungeon;
|
||||
|
||||
std::vector<RandomizerGet> StartingInventory;
|
||||
uint8_t AdditionalHeartContainers;
|
||||
|
||||
@@ -15,10 +13,11 @@ static void AddItemToInventory(RandomizerGet item, size_t count = 1) {
|
||||
}
|
||||
|
||||
void GenerateStartingInventory() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
StartingInventory.clear();
|
||||
|
||||
if (MapsAndCompasses.Is(MAPSANDCOMPASSES_START_WITH)) {
|
||||
for (auto* dungeon : dungeonList) {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_STARTWITH)) {
|
||||
for (auto* dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
if (dungeon->GetMap() != RG_NONE) {
|
||||
AddItemToInventory(dungeon->GetMap());
|
||||
}
|
||||
@@ -29,24 +28,24 @@ void GenerateStartingInventory() {
|
||||
}
|
||||
}
|
||||
|
||||
if (Keysanity.Is(KEYSANITY_START_WITH)) {
|
||||
for (auto* dungeon : dungeonList) {
|
||||
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_STARTWITH)) {
|
||||
for (auto* dungeon : ctx->GetDungeons()->GetDungeonList()) {
|
||||
if (dungeon->GetSmallKeyCount() > 0) {
|
||||
AddItemToInventory(dungeon->GetSmallKey(), dungeon->GetSmallKeyCount());
|
||||
}
|
||||
}
|
||||
} else if (Keysanity.Is(KEYSANITY_VANILLA)) {
|
||||
} else if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA)) {
|
||||
// Logic cannot handle vanilla key layout in some dungeons
|
||||
// this is because vanilla expects the dungeon major item to be
|
||||
// locked behind the keys, which is not always true in rando.
|
||||
// We can resolve this by starting with some extra keys
|
||||
// - OoT Randomizer
|
||||
if (SpiritTemple.IsMQ()) {
|
||||
if (ctx->GetDungeon(Rando::SPIRIT_TEMPLE)->IsMQ()) {
|
||||
AddItemToInventory(RG_SPIRIT_TEMPLE_SMALL_KEY, 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (BossKeysanity.Is(BOSSKEYSANITY_START_WITH)) {
|
||||
if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_STARTWITH)) {
|
||||
AddItemToInventory(RG_FOREST_TEMPLE_BOSS_KEY);
|
||||
AddItemToInventory(RG_FIRE_TEMPLE_BOSS_KEY);
|
||||
AddItemToInventory(RG_WATER_TEMPLE_BOSS_KEY);
|
||||
@@ -56,11 +55,12 @@ void GenerateStartingInventory() {
|
||||
|
||||
// Add Ganon's Boss key with Triforce Hunt so the game thinks it's obtainable from the start.
|
||||
// During save init, the boss key isn't actually given and it's instead given when completing the triforce.
|
||||
if (GanonsBossKey.Is(GANONSBOSSKEY_START_WITH) || GanonsBossKey.Is(GANONSBOSSKEY_TRIFORCE_HUNT)) {
|
||||
AddItemToInventory(RG_GANONS_CASTLE_BOSS_KEY);
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH) ||
|
||||
ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
|
||||
AddItemToInventory(RG_GANONS_CASTLE_BOSS_KEY);
|
||||
}
|
||||
|
||||
if (GerudoFortress.Is(GERUDOFORTRESS_OPEN) && !ShuffleGerudoToken) {
|
||||
if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_OPEN) && !ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
|
||||
AddItemToInventory(RG_GERUDO_MEMBERSHIP_CARD);
|
||||
}
|
||||
|
||||
@@ -68,103 +68,104 @@ void GenerateStartingInventory() {
|
||||
//Values are associated so that the count of items matches the index of
|
||||
//the option selected. If None is selected, the value will be zero and
|
||||
//zero of the item will be added to the starting inventory.
|
||||
AddItemToInventory(RG_PROGRESSIVE_STICK_UPGRADE, StartingStickCapacity.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_NUT_UPGRADE, StartingNutCapacity.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_BOMB_BAG, StartingBombBag.Value<uint8_t>());
|
||||
AddItemToInventory((BombchusInLogic ? RG_PROGRESSIVE_BOMBCHUS : RG_BOMBCHU_20), StartingBombchus.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_BOW, StartingBow.Value<uint8_t>());
|
||||
AddItemToInventory(RG_FIRE_ARROWS, StartingFireArrows.Value<uint8_t>());
|
||||
AddItemToInventory(RG_ICE_ARROWS, StartingIceArrows.Value<uint8_t>());
|
||||
AddItemToInventory(RG_LIGHT_ARROWS, StartingLightArrows.Value<uint8_t>());
|
||||
AddItemToInventory(RG_DINS_FIRE, StartingDinsFire.Value<uint8_t>());
|
||||
AddItemToInventory(RG_FARORES_WIND, StartingFaroresWind.Value<uint8_t>());
|
||||
AddItemToInventory(RG_NAYRUS_LOVE, StartingNayrusLove.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_SLINGSHOT, StartingSlingshot.Value<uint8_t>());
|
||||
AddItemToInventory(RG_BOOMERANG, StartingBoomerang.Value<uint8_t>());
|
||||
AddItemToInventory(RG_LENS_OF_TRUTH, StartingLensOfTruth.Value<uint8_t>());
|
||||
AddItemToInventory(RG_MAGIC_BEAN_PACK, StartingMagicBean.Value<uint8_t>());
|
||||
AddItemToInventory(RG_MEGATON_HAMMER, StartingMegatonHammer.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_HOOKSHOT, StartingHookshot.Value<uint8_t>());
|
||||
AddItemToInventory(RG_IRON_BOOTS, StartingIronBoots.Value<uint8_t>());
|
||||
AddItemToInventory(RG_HOVER_BOOTS, StartingHoverBoots.Value<uint8_t>());
|
||||
// TODO: Uncomment when these options are implemented.
|
||||
// AddItemToInventory(RG_PROGRESSIVE_STICK_UPGRADE, StartingStickCapacity.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_PROGRESSIVE_NUT_UPGRADE, StartingNutCapacity.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_PROGRESSIVE_BOMB_BAG, StartingBombBag.Value<uint8_t>());
|
||||
// AddItemToInventory((BombchusInLogic ? RG_PROGRESSIVE_BOMBCHUS : RG_BOMBCHU_20), StartingBombchus.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_PROGRESSIVE_BOW, StartingBow.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_FIRE_ARROWS, StartingFireArrows.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_ICE_ARROWS, StartingIceArrows.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_LIGHT_ARROWS, StartingLightArrows.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_DINS_FIRE, StartingDinsFire.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_FARORES_WIND, StartingFaroresWind.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_NAYRUS_LOVE, StartingNayrusLove.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_PROGRESSIVE_SLINGSHOT, StartingSlingshot.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_BOOMERANG, StartingBoomerang.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_LENS_OF_TRUTH, StartingLensOfTruth.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_MAGIC_BEAN_PACK, StartingMagicBean.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_MEGATON_HAMMER, StartingMegatonHammer.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_PROGRESSIVE_HOOKSHOT, StartingHookshot.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_IRON_BOOTS, StartingIronBoots.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_HOVER_BOOTS, StartingHoverBoots.Value<uint8_t>());
|
||||
//For starting bottles, we need to check if they are a big poe and add that if so
|
||||
// since a big poe bottle is not logically equivalent to an empty bottle.
|
||||
if (StartingBottle1.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
|
||||
AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
|
||||
} else if (StartingBottle1.Value<uint8_t>()) {
|
||||
AddItemToInventory(RG_EMPTY_BOTTLE, 1);
|
||||
}
|
||||
if (StartingBottle2.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
|
||||
AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
|
||||
} else if (StartingBottle2.Value<uint8_t>()) {
|
||||
AddItemToInventory(RG_EMPTY_BOTTLE, 1);
|
||||
}
|
||||
if (StartingBottle3.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
|
||||
AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
|
||||
} else if (StartingBottle3.Value<uint8_t>()) {
|
||||
AddItemToInventory(RG_EMPTY_BOTTLE, 1);
|
||||
}
|
||||
if (StartingBottle4.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
|
||||
AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
|
||||
} else if (StartingBottle4.Value<uint8_t>()) {
|
||||
AddItemToInventory(RG_EMPTY_BOTTLE, 1);
|
||||
}
|
||||
AddItemToInventory(RG_RUTOS_LETTER, StartingRutoBottle.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_OCARINA, StartingOcarina.Value<uint8_t>());
|
||||
AddItemToInventory(RG_ZELDAS_LULLABY, StartingZeldasLullaby.Value<uint8_t>());
|
||||
AddItemToInventory(RG_EPONAS_SONG, StartingEponasSong.Value<uint8_t>());
|
||||
AddItemToInventory(RG_SARIAS_SONG, StartingSariasSong.Value<uint8_t>());
|
||||
AddItemToInventory(RG_SUNS_SONG, StartingSunsSong.Value<uint8_t>());
|
||||
AddItemToInventory(RG_SONG_OF_TIME, StartingSongOfTime.Value<uint8_t>());
|
||||
AddItemToInventory(RG_SONG_OF_STORMS, StartingSongOfStorms.Value<uint8_t>());
|
||||
AddItemToInventory(RG_MINUET_OF_FOREST, StartingMinuetOfForest.Value<uint8_t>());
|
||||
AddItemToInventory(RG_BOLERO_OF_FIRE, StartingBoleroOfFire.Value<uint8_t>());
|
||||
AddItemToInventory(RG_SERENADE_OF_WATER, StartingSerenadeOfWater.Value<uint8_t>());
|
||||
AddItemToInventory(RG_REQUIEM_OF_SPIRIT, StartingRequiemOfSpirit.Value<uint8_t>());
|
||||
AddItemToInventory(RG_NOCTURNE_OF_SHADOW, StartingNocturneOfShadow.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PRELUDE_OF_LIGHT, StartingPreludeOfLight.Value<uint8_t>());
|
||||
AddItemToInventory(RG_KOKIRI_SWORD, StartingKokiriSword.Value<uint8_t>());
|
||||
if (ProgressiveGoronSword) {
|
||||
AddItemToInventory(RG_PROGRESSIVE_GORONSWORD, StartingBiggoronSword.Value<uint8_t>());
|
||||
} else {
|
||||
AddItemToInventory(RG_GIANTS_KNIFE, (StartingBiggoronSword.Is(STARTINGBGS_GIANTS_KNIFE)) ? 1 : 0);
|
||||
AddItemToInventory(RG_BIGGORON_SWORD, (StartingBiggoronSword.Is(STARTINGBGS_BIGGORON_SWORD)) ? 1 : 0);
|
||||
}
|
||||
AddItemToInventory(RG_DEKU_SHIELD, StartingDekuShield.Value<uint8_t>());
|
||||
AddItemToInventory(RG_HYLIAN_SHIELD, StartingHylianShield.Value<uint8_t>());
|
||||
AddItemToInventory(RG_MIRROR_SHIELD, StartingMirrorShield.Value<uint8_t>());
|
||||
AddItemToInventory(RG_GORON_TUNIC, StartingGoronTunic.Value<uint8_t>());
|
||||
AddItemToInventory(RG_ZORA_TUNIC, StartingZoraTunic.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_MAGIC_METER, StartingMagicMeter.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_STRENGTH, StartingStrength.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_SCALE, StartingScale.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_WALLET, StartingWallet.Value<uint8_t>());
|
||||
AddItemToInventory(RG_STONE_OF_AGONY, StartingShardOfAgony.Value<uint8_t>());
|
||||
AddItemToInventory(RG_DOUBLE_DEFENSE, StartingDoubleDefense.Value<uint8_t>());
|
||||
AddItemToInventory(RG_KOKIRI_EMERALD, StartingKokiriEmerald.Value<uint8_t>());
|
||||
AddItemToInventory(RG_GORON_RUBY, StartingGoronRuby.Value<uint8_t>());
|
||||
AddItemToInventory(RG_ZORA_SAPPHIRE, StartingZoraSapphire.Value<uint8_t>());
|
||||
AddItemToInventory(RG_FOREST_MEDALLION, StartingForestMedallion.Value<uint8_t>());
|
||||
AddItemToInventory(RG_FIRE_MEDALLION, StartingFireMedallion.Value<uint8_t>());
|
||||
AddItemToInventory(RG_WATER_MEDALLION, StartingWaterMedallion.Value<uint8_t>());
|
||||
AddItemToInventory(RG_SPIRIT_MEDALLION, StartingSpiritMedallion.Value<uint8_t>());
|
||||
AddItemToInventory(RG_SHADOW_MEDALLION, StartingShadowMedallion.Value<uint8_t>());
|
||||
AddItemToInventory(RG_LIGHT_MEDALLION, StartingLightMedallion.Value<uint8_t>());
|
||||
AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, StartingSkulltulaToken.Value<uint8_t>());
|
||||
// if (StartingBottle1.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
|
||||
// AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
|
||||
// } else if (StartingBottle1.Value<uint8_t>()) {
|
||||
// AddItemToInventory(RG_EMPTY_BOTTLE, 1);
|
||||
// }
|
||||
// if (StartingBottle2.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
|
||||
// AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
|
||||
// } else if (StartingBottle2.Value<uint8_t>()) {
|
||||
// AddItemToInventory(RG_EMPTY_BOTTLE, 1);
|
||||
// }
|
||||
// if (StartingBottle3.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
|
||||
// AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
|
||||
// } else if (StartingBottle3.Value<uint8_t>()) {
|
||||
// AddItemToInventory(RG_EMPTY_BOTTLE, 1);
|
||||
// }
|
||||
// if (StartingBottle4.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
|
||||
// AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
|
||||
// } else if (StartingBottle4.Value<uint8_t>()) {
|
||||
// AddItemToInventory(RG_EMPTY_BOTTLE, 1);
|
||||
// }
|
||||
// AddItemToInventory(RG_RUTOS_LETTER, StartingRutoBottle.Value<uint8_t>());
|
||||
AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).Value<uint8_t>());
|
||||
AddItemToInventory(RG_ZELDAS_LULLABY, ctx->GetOption(RSK_STARTING_ZELDAS_LULLABY) ? 1 : 0);
|
||||
AddItemToInventory(RG_EPONAS_SONG, ctx->GetOption(RSK_STARTING_EPONAS_SONG) ? 1 : 0);
|
||||
AddItemToInventory(RG_SARIAS_SONG, ctx->GetOption(RSK_STARTING_SARIAS_SONG) ? 1 : 0);
|
||||
AddItemToInventory(RG_SUNS_SONG, ctx->GetOption(RSK_STARTING_SUNS_SONG) ? 1 : 0);
|
||||
AddItemToInventory(RG_SONG_OF_TIME, ctx->GetOption(RSK_STARTING_SONG_OF_TIME) ? 1 : 0);
|
||||
AddItemToInventory(RG_SONG_OF_STORMS, ctx->GetOption(RSK_STARTING_SONG_OF_STORMS) ? 1 : 0);
|
||||
AddItemToInventory(RG_MINUET_OF_FOREST, ctx->GetOption(RSK_STARTING_MINUET_OF_FOREST) ? 1 : 0);
|
||||
AddItemToInventory(RG_BOLERO_OF_FIRE, ctx->GetOption(RSK_STARTING_BOLERO_OF_FIRE) ? 1 : 0);
|
||||
AddItemToInventory(RG_SERENADE_OF_WATER, ctx->GetOption(RSK_STARTING_SERENADE_OF_WATER) ? 1 : 0);
|
||||
AddItemToInventory(RG_REQUIEM_OF_SPIRIT, ctx->GetOption(RSK_STARTING_REQUIEM_OF_SPIRIT) ? 1 : 0);
|
||||
AddItemToInventory(RG_NOCTURNE_OF_SHADOW, ctx->GetOption(RSK_STARTING_NOCTURNE_OF_SHADOW) ? 1 : 0);
|
||||
AddItemToInventory(RG_PRELUDE_OF_LIGHT, ctx->GetOption(RSK_STARTING_PRELUDE_OF_LIGHT) ? 1 : 0);
|
||||
AddItemToInventory(RG_KOKIRI_SWORD, ctx->GetOption(RSK_STARTING_KOKIRI_SWORD) ? 1 : 0);
|
||||
// if (ProgressiveGoronSword) {
|
||||
// AddItemToInventory(RG_PROGRESSIVE_GORONSWORD, StartingBiggoronSword.Value<uint8_t>());
|
||||
// } else {
|
||||
// AddItemToInventory(RG_GIANTS_KNIFE, (StartingBiggoronSword.Is(STARTINGBGS_GIANTS_KNIFE)) ? 1 : 0);
|
||||
// AddItemToInventory(RG_BIGGORON_SWORD, (StartingBiggoronSword.Is(STARTINGBGS_BIGGORON_SWORD)) ? 1 : 0);
|
||||
// }
|
||||
AddItemToInventory(RG_DEKU_SHIELD, ctx->GetOption(RSK_STARTING_DEKU_SHIELD) ? 1 : 0);
|
||||
// AddItemToInventory(RG_HYLIAN_SHIELD, StartingHylianShield.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_MIRROR_SHIELD, StartingMirrorShield.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_GORON_TUNIC, StartingGoronTunic.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_ZORA_TUNIC, StartingZoraTunic.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_PROGRESSIVE_MAGIC_METER, StartingMagicMeter.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_PROGRESSIVE_STRENGTH, StartingStrength.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_PROGRESSIVE_SCALE, StartingScale.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_PROGRESSIVE_WALLET, StartingWallet.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_STONE_OF_AGONY, StartingShardOfAgony.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_DOUBLE_DEFENSE, StartingDoubleDefense.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_KOKIRI_EMERALD, StartingKokiriEmerald.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_GORON_RUBY, StartingGoronRuby.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_ZORA_SAPPHIRE, StartingZoraSapphire.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_FOREST_MEDALLION, StartingForestMedallion.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_FIRE_MEDALLION, StartingFireMedallion.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_WATER_MEDALLION, StartingWaterMedallion.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_SPIRIT_MEDALLION, StartingSpiritMedallion.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_SHADOW_MEDALLION, StartingShadowMedallion.Value<uint8_t>());
|
||||
// AddItemToInventory(RG_LIGHT_MEDALLION, StartingLightMedallion.Value<uint8_t>());
|
||||
AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Value<uint8_t>());
|
||||
|
||||
int8_t hearts = StartingHearts.Value<uint8_t>() - 2;
|
||||
int8_t hearts = ctx->GetOption(RSK_STARTING_HEARTS).Value<uint8_t>() - 2;
|
||||
AdditionalHeartContainers = 0;
|
||||
if (hearts < 0) {
|
||||
AddItemToInventory(RG_PIECE_OF_HEART, 4);
|
||||
// Plentiful and minimal have less than 4 standard pieces of heart so also replace the winner heart
|
||||
if (ItemPoolValue.Value<uint8_t>() == 0 || ItemPoolValue.Value<uint8_t>() == 3) {
|
||||
if (ctx->GetOption(RSK_ITEM_POOL).Value<uint8_t>() == 0 || ctx->GetOption(RSK_ITEM_POOL).Value<uint8_t>() == 3) {
|
||||
AddItemToInventory(RG_TREASURE_GAME_HEART);
|
||||
}
|
||||
|
||||
AdditionalHeartContainers = 1 - hearts;
|
||||
} else if (hearts > 0) {
|
||||
// 16 containers in plentiful, 8 in balanced and 0 in the others
|
||||
uint8_t maxContainers = 8 * std::max(0, 2 - ItemPoolValue.Value<uint8_t>());
|
||||
uint8_t maxContainers = 8 * std::max(0, 2 - ctx->GetOption(RSK_ITEM_POOL).Value<uint8_t>());
|
||||
|
||||
if (hearts <= maxContainers) {
|
||||
AddItemToInventory(RG_HEART_CONTAINER, hearts);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "z64.h"
|
||||
|
||||
#define PLURAL 0
|
||||
#define SINGULAR 1
|
||||
@@ -12,6 +13,7 @@ public:
|
||||
: english(std::move(english_)),
|
||||
french(std::move(french_)),
|
||||
spanish(std::move(spanish_)) {}
|
||||
Text(std::string english_) : english(std::move(english_)), french(std::move("")), spanish(std::move("")) {}
|
||||
|
||||
const std::string& GetEnglish() const {
|
||||
return english;
|
||||
@@ -31,6 +33,18 @@ public:
|
||||
return english;
|
||||
}
|
||||
|
||||
const std::string& GetForLanguage(uint8_t language) const {
|
||||
switch (language) {
|
||||
case LANGUAGE_ENG:
|
||||
return english;
|
||||
case LANGUAGE_FRA:
|
||||
return french;
|
||||
case LANGUAGE_GER:
|
||||
default:
|
||||
return english; // TODO: German
|
||||
}
|
||||
}
|
||||
|
||||
Text operator+ (const Text& right) const {
|
||||
return Text{english + right.GetEnglish(), french + right.GetFrench(), spanish + right.GetSpanish()};
|
||||
}
|
||||
@@ -43,6 +57,10 @@ public:
|
||||
return english == right.english;
|
||||
}
|
||||
|
||||
bool operator==(const std::string& right) const {
|
||||
return english == right || french == right || spanish == right;
|
||||
}
|
||||
|
||||
bool operator!=(const Text& right) const {
|
||||
return !operator==(right);
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#include "trial.hpp"
|
||||
|
||||
namespace Trial {
|
||||
|
||||
TrialInfo::TrialInfo(Text name_)
|
||||
: name(std::move(name_)) {}
|
||||
|
||||
TrialInfo::~TrialInfo() = default;
|
||||
|
||||
TrialInfo ForestTrial = TrialInfo(Text{"the Forest Trial", /*french*/"l'épreuve de la Forêt", /*spanish*/"la prueba del bosque"});
|
||||
TrialInfo FireTrial = TrialInfo(Text{"the Fire Trial", /*french*/"l'épreuve du Feu", /*spanish*/"la prueba del fuego"});
|
||||
TrialInfo WaterTrial = TrialInfo(Text{"the Water Trial", /*french*/"l'épreuve de l'Eau", /*spanish*/"la prueba del agua"});
|
||||
TrialInfo SpiritTrial = TrialInfo(Text{"the Spirit Trial", /*french*/"l'épreuve de l'Esprit", /*spanish*/"la prueba del espíritu"});
|
||||
TrialInfo ShadowTrial = TrialInfo(Text{"the Shadow Trial", /*french*/"l'épreuve de l'Ombre", /*spanish*/"la prueba de las sombras"});
|
||||
TrialInfo LightTrial = TrialInfo(Text{"the Light Trial", /*french*/"l'épreuve de la Lumière", /*spanish*/"la prueba de la luz"});
|
||||
|
||||
const TrialArray trialList = {
|
||||
&ForestTrial,
|
||||
&FireTrial,
|
||||
&WaterTrial,
|
||||
&SpiritTrial,
|
||||
&ShadowTrial,
|
||||
&LightTrial,
|
||||
};
|
||||
|
||||
} //namespace Trial
|
||||
@@ -1,51 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "text.hpp"
|
||||
|
||||
//This is probably overkill for a small amount of information, but we can add
|
||||
//stuff later if we want
|
||||
|
||||
namespace Trial {
|
||||
class TrialInfo {
|
||||
public:
|
||||
TrialInfo(const Text name_);
|
||||
~TrialInfo();
|
||||
|
||||
Text GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
bool IsSkipped() const {
|
||||
return skipped;
|
||||
}
|
||||
|
||||
bool IsRequired() const {
|
||||
return !skipped;
|
||||
}
|
||||
|
||||
void SetAsRequired() {
|
||||
skipped = false;
|
||||
}
|
||||
|
||||
void SetAsSkipped() {
|
||||
skipped = true;
|
||||
}
|
||||
|
||||
private:
|
||||
Text name;
|
||||
bool skipped = true;
|
||||
};
|
||||
|
||||
extern TrialInfo ForestTrial;
|
||||
extern TrialInfo FireTrial;
|
||||
extern TrialInfo WaterTrial;
|
||||
extern TrialInfo SpiritTrial;
|
||||
extern TrialInfo ShadowTrial;
|
||||
extern TrialInfo LightTrial;
|
||||
|
||||
using TrialArray = std::array<TrialInfo*, 6>;
|
||||
|
||||
extern const TrialArray trialList;
|
||||
} //namespace Trial
|
||||
@@ -1,17 +1,58 @@
|
||||
#include "context.h"
|
||||
#include "static_data.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/item-tables/ItemTableManager.h"
|
||||
#include "3drando/shops.hpp"
|
||||
#include "3drando/dungeon.hpp"
|
||||
#include "dungeon.h"
|
||||
#include "trial.h"
|
||||
#include "entrance.h"
|
||||
#include "settings.h"
|
||||
#include "rando_hash.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace Rando {
|
||||
std::weak_ptr<Context> Context::mContext;
|
||||
|
||||
Context::Context() {
|
||||
for (auto& location : StaticData::GetLocationTable()) {
|
||||
mSpoilerfileCheckNameToEnum[location.GetName()] = location.GetRandomizerCheck();
|
||||
}
|
||||
mSpoilerfileCheckNameToEnum["Invalid Location"] = RC_UNKNOWN_CHECK;
|
||||
mSpoilerfileCheckNameToEnum["Link's Pocket"] = RC_LINKS_POCKET;
|
||||
|
||||
for (auto& item : StaticData::GetItemTable()) {
|
||||
// Easiest way to filter out all the empty values from the array, since we still technically want the 0/RG_NONE
|
||||
// entry
|
||||
if (item.GetName().english.empty())
|
||||
continue;
|
||||
mSpoilerfileGetNameToEnum[item.GetName().english] = item.GetRandomizerGet();
|
||||
mSpoilerfileGetNameToEnum[item.GetName().french] = item.GetRandomizerGet();
|
||||
}
|
||||
mSpoilerfileHintTypeNameToEnum = {
|
||||
{ "Trial", HINT_TYPE_TRIAL },
|
||||
{ "Always", HINT_TYPE_ALWAYS },
|
||||
{ "WotH", HINT_TYPE_WOTH },
|
||||
{ "Barren", HINT_TYPE_BARREN },
|
||||
{ "Entrance", HINT_TYPE_ENTRANCE },
|
||||
{ "Sometimes", HINT_TYPE_SOMETIMES },
|
||||
{ "Random", HINT_TYPE_RANDOM },
|
||||
{ "Static", HINT_TYPE_STATIC },
|
||||
{ "Song", HINT_TYPE_SONG },
|
||||
{ "Overworld", HINT_TYPE_OVERWORLD },
|
||||
{ "Dungeon", HINT_TYPE_DUNGEON },
|
||||
{ "Junk", HINT_TYPE_JUNK },
|
||||
{ "Named Item", HINT_TYPE_NAMED_ITEM },
|
||||
{ "Random", HINT_TYPE_RANDOM }
|
||||
};
|
||||
for (int i = 0; i < RC_MAX; i++) {
|
||||
itemLocationTable[i] = ItemLocation((RandomizerCheck)i);
|
||||
}
|
||||
mEntranceShuffler = std::make_shared<EntranceShuffler>();
|
||||
mDungeons = std::make_shared<Dungeons>();
|
||||
mTrials = std::make_shared<Trials>();
|
||||
mSettings = std::make_shared<Settings>();
|
||||
}
|
||||
|
||||
std::shared_ptr<Context> Context::CreateInstance() {
|
||||
@@ -27,7 +68,7 @@ std::shared_ptr<Context> Context::GetInstance() {
|
||||
return mContext.lock();
|
||||
}
|
||||
|
||||
Hint *Context::GetHint(RandomizerHintKey hintKey) {
|
||||
Hint* Context::GetHint(RandomizerHintKey hintKey) {
|
||||
return &hintTable[hintKey];
|
||||
}
|
||||
|
||||
@@ -37,10 +78,14 @@ void Context::AddHint(RandomizerHintKey hintId, Text text, RandomizerCheck hinte
|
||||
GetItemLocation(hintedLocation)->SetHintKey(hintId);
|
||||
}
|
||||
|
||||
ItemLocation *Context::GetItemLocation(RandomizerCheck locKey) {
|
||||
ItemLocation* Context::GetItemLocation(RandomizerCheck locKey) {
|
||||
return &(itemLocationTable[locKey]);
|
||||
}
|
||||
|
||||
ItemLocation* Context::GetItemLocation(size_t locKey) {
|
||||
return &(itemLocationTable[static_cast<RandomizerCheck>(locKey)]);
|
||||
}
|
||||
|
||||
void Context::PlaceItemInLocation(RandomizerCheck locKey, RandomizerGet item, bool applyEffectImmediately,
|
||||
bool setHidden) {
|
||||
auto loc = GetItemLocation(locKey);
|
||||
@@ -50,19 +95,20 @@ void Context::PlaceItemInLocation(RandomizerCheck locKey, RandomizerGet item, bo
|
||||
SPDLOG_DEBUG(StaticData::GetLocation(locKey)->GetName());
|
||||
SPDLOG_DEBUG("\n\n");
|
||||
|
||||
if (applyEffectImmediately || Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
if (applyEffectImmediately || mSettings->Setting(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS) || mSettings->Setting(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
|
||||
Rando::StaticData::RetrieveItem(item).ApplyEffect();
|
||||
}
|
||||
|
||||
//TODO? Show Progress
|
||||
// TODO? Show Progress
|
||||
|
||||
// If we're placing a non-shop item in a shop location, we want to record it for custom messages
|
||||
if (StaticData::RetrieveItem(item).GetItemType() != ITEMTYPE_SHOP &&
|
||||
Rando::StaticData::GetLocation(locKey)->IsCategory(Category::cShop)) {
|
||||
int index = TransformShopIndex(GetShopIndex(locKey));
|
||||
NonShopItems[index].Name = Rando::StaticData::RetrieveItem(item).GetName();
|
||||
NonShopItems[index].Repurchaseable = Rando::StaticData::RetrieveItem(item).GetItemType() == ITEMTYPE_REFILL ||
|
||||
Rando::StaticData::RetrieveItem(item).GetHintKey() == RHT_PROGRESSIVE_BOMBCHUS;
|
||||
NonShopItems[index].Repurchaseable =
|
||||
Rando::StaticData::RetrieveItem(item).GetItemType() == ITEMTYPE_REFILL ||
|
||||
Rando::StaticData::RetrieveItem(item).GetHintKey() == RHT_PROGRESSIVE_BOMBCHUS;
|
||||
}
|
||||
|
||||
loc->SetPlacedItem(item);
|
||||
@@ -78,7 +124,7 @@ void Context::AddLocation(RandomizerCheck loc, std::vector<RandomizerCheck>* des
|
||||
destination->push_back(loc);
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
template <typename Container>
|
||||
void Context::AddLocations(const Container& locations, std::vector<RandomizerCheck>* destination) {
|
||||
if (destination == nullptr) {
|
||||
destination = &allLocations;
|
||||
@@ -89,19 +135,19 @@ void Context::AddLocations(const Container& locations, std::vector<RandomizerChe
|
||||
void Context::GenerateLocationPool() {
|
||||
allLocations.clear();
|
||||
AddLocation(RC_LINKS_POCKET);
|
||||
if (Settings::TriforceHunt.Is(TRIFORCE_HUNT_ON)) {
|
||||
if (mSettings->Setting(RSK_TRIFORCE_HUNT)) {
|
||||
AddLocation(RC_TRIFORCE_COMPLETED);
|
||||
}
|
||||
AddLocations(StaticData::overworldLocations);
|
||||
|
||||
for (auto dungeon : Dungeon::dungeonList) {
|
||||
for (auto dungeon : mDungeons->GetDungeonList()) {
|
||||
AddLocations(dungeon->GetDungeonLocations());
|
||||
}
|
||||
}
|
||||
|
||||
void Context::AddExcludedOptions() {
|
||||
AddLocations(StaticData::overworldLocations, &everyPossibleLocation);
|
||||
for (auto dungeon : Dungeon::dungeonList) {
|
||||
for (auto dungeon : mDungeons->GetDungeonList()) {
|
||||
AddLocations(dungeon->GetEveryLocation(), &everyPossibleLocation);
|
||||
}
|
||||
for (RandomizerCheck rc : everyPossibleLocation) {
|
||||
@@ -144,15 +190,13 @@ void Context::LocationReset() {
|
||||
GetItemLocation(il)->RemoveFromPool();
|
||||
}
|
||||
|
||||
for (RandomizerCheck il : Rando::StaticData::otherHintLocations) {
|
||||
GetItemLocation(il)->RemoveFromPool();
|
||||
}
|
||||
GetItemLocation(RC_GANONDORF_HINT)->RemoveFromPool();
|
||||
}
|
||||
|
||||
void Context::HintReset() {
|
||||
for (RandomizerCheck il : Rando::StaticData::gossipStoneLocations) {
|
||||
GetItemLocation(il)->ResetVariables();
|
||||
GetHint((RandomizerHintKey)(il - RC_DMC_GOSSIP_STONE + 1))->ResetVariables();
|
||||
GetHint((RandomizerHintKey)(il - RC_COLOSSUS_GOSSIP_STONE + 1))->ResetVariables();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,24 +205,17 @@ void Context::CreateItemOverrides() {
|
||||
for (RandomizerCheck locKey : allLocations) {
|
||||
auto loc = Rando::StaticData::GetLocation(locKey);
|
||||
auto itemLoc = GetItemLocation(locKey);
|
||||
ItemOverride_Value val = Rando::StaticData::RetrieveItem(itemLoc->GetPlacedRandomizerGet()).Value();
|
||||
// If this is an ice trap, store the disguise model in iceTrapModels
|
||||
if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP) {
|
||||
iceTrapModels[loc->GetRandomizerCheck()] = val.looksLikeItemId;
|
||||
ItemOverride val(locKey, RandomElement(possibleIceTrapModels));
|
||||
iceTrapModels[locKey] = val.LooksLike();
|
||||
val.SetTrickName(GetIceTrapName(val.LooksLike()));
|
||||
// If this is ice trap is in a shop, change the name based on what the model will look like
|
||||
if (loc->IsCategory(Category::cShop)) {
|
||||
NonShopItems[TransformShopIndex(GetShopIndex(locKey))].Name = GetIceTrapName(val.looksLikeItemId);
|
||||
NonShopItems[TransformShopIndex(GetShopIndex(locKey))].Name = val.GetTrickName();
|
||||
}
|
||||
overrides[locKey] = val;
|
||||
}
|
||||
overrides.insert({
|
||||
.key = itemLoc->Key(),
|
||||
.value = val,
|
||||
});
|
||||
SPDLOG_DEBUG("\tScene: ");
|
||||
SPDLOG_DEBUG(std::to_string(itemLoc->Key().scene));
|
||||
SPDLOG_DEBUG("\tType: ");
|
||||
SPDLOG_DEBUG(std::to_string(itemLoc->Key().type));
|
||||
SPDLOG_DEBUG("\t");
|
||||
SPDLOG_DEBUG(loc->GetName());
|
||||
SPDLOG_DEBUG(": ");
|
||||
SPDLOG_DEBUG(itemLoc->GetPlacedItemName().GetEnglish());
|
||||
@@ -187,4 +224,339 @@ void Context::CreateItemOverrides() {
|
||||
SPDLOG_DEBUG("Overrides Created: ");
|
||||
SPDLOG_DEBUG(std::to_string(overrides.size()));
|
||||
}
|
||||
|
||||
bool Context::IsSeedGenerated() {
|
||||
return mSeedGenerated;
|
||||
}
|
||||
|
||||
void Context::SetSeedGenerated(bool seedGenerated) {
|
||||
mSeedGenerated = seedGenerated;
|
||||
}
|
||||
|
||||
bool Context::IsSpoilerLoaded() {
|
||||
return mSpoilerLoaded;
|
||||
}
|
||||
|
||||
void Context::SetSpoilerLoaded(bool spoilerLoaded) {
|
||||
mSpoilerLoaded = spoilerLoaded;
|
||||
}
|
||||
|
||||
bool Context::IsPlandoLoaded() {
|
||||
return mPlandoLoaded;
|
||||
}
|
||||
|
||||
void Context::SetPlandoLoaded(bool plandoLoaded) {
|
||||
mPlandoLoaded = plandoLoaded;
|
||||
}
|
||||
|
||||
GetItemEntry Context::GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability, GetItemID ogItemId) {
|
||||
auto itemLoc = GetItemLocation(rc);
|
||||
if (itemLoc->GetPlacedRandomizerGet() == RG_NONE) {
|
||||
if (ogItemId != GI_NONE) {
|
||||
return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, ogItemId);
|
||||
}
|
||||
return ItemTableManager::Instance->RetrieveItemEntry(
|
||||
MOD_NONE, StaticData::RetrieveItem(StaticData::GetLocation(rc)->GetVanillaItem()).GetItemID());
|
||||
}
|
||||
if (checkObtainability && OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerGet(
|
||||
itemLoc->GetPlacedRandomizerGet()) != CAN_OBTAIN) {
|
||||
return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, GI_RUPEE_BLUE);
|
||||
}
|
||||
GetItemEntry giEntry = itemLoc->GetPlacedItem().GetGIEntry_Copy();
|
||||
if (overrides.contains(rc)) {
|
||||
auto fakeGiEntry = StaticData::RetrieveItem(overrides[rc].LooksLike()).GetGIEntry();
|
||||
giEntry.gid = fakeGiEntry->gid;
|
||||
giEntry.gi = fakeGiEntry->gi;
|
||||
giEntry.drawItemId = fakeGiEntry->drawItemId;
|
||||
giEntry.drawModIndex = fakeGiEntry->drawModIndex;
|
||||
giEntry.drawFunc = fakeGiEntry->drawFunc;
|
||||
}
|
||||
return giEntry;
|
||||
}
|
||||
|
||||
std::string sanitize(std::string stringValue) {
|
||||
// Add backslashes.
|
||||
for (auto i = stringValue.begin();;) {
|
||||
auto const pos =
|
||||
std::find_if(i, stringValue.end(), [](char const c) { return '\\' == c || '\'' == c || '"' == c; });
|
||||
if (pos == stringValue.end()) {
|
||||
break;
|
||||
}
|
||||
i = std::next(stringValue.insert(pos, '\\'), 2);
|
||||
}
|
||||
|
||||
// Removes others.
|
||||
stringValue.erase(std::remove_if(stringValue.begin(), stringValue.end(),
|
||||
[](char const c) { return '\n' == c || '\r' == c || '\0' == c || '\x1A' == c; }),
|
||||
stringValue.end());
|
||||
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
void Context::ParseSpoiler(const char* spoilerFileName, bool plandoMode) {
|
||||
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
|
||||
if (!spoilerFileStream) {
|
||||
return;
|
||||
}
|
||||
mSeedGenerated = false;
|
||||
mSpoilerLoaded = false;
|
||||
mPlandoLoaded = false;
|
||||
try {
|
||||
nlohmann::json spoilerFileJson;
|
||||
spoilerFileStream >> spoilerFileJson;
|
||||
ParseHashIconIndexesJson(spoilerFileJson);
|
||||
mSettings->ParseJson(spoilerFileJson);
|
||||
if (plandoMode) {
|
||||
ParseItemLocationsJson(spoilerFileJson);
|
||||
ParseHintJson(spoilerFileJson);
|
||||
mEntranceShuffler->ParseJson(spoilerFileJson);
|
||||
mDungeons->ParseJson(spoilerFileJson);
|
||||
mTrials->ParseJson(spoilerFileJson);
|
||||
mPlandoLoaded = true;
|
||||
}
|
||||
mSpoilerLoaded = true;
|
||||
mSeedGenerated = false;
|
||||
} catch (std::exception& e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
void Context::ParseHashIconIndexesJson(nlohmann::json spoilerFileJson) {
|
||||
nlohmann::json hashJson = spoilerFileJson["file_hash"];
|
||||
int index = 0;
|
||||
for (auto it = hashJson.begin(); it != hashJson.end(); ++it) {
|
||||
hashIconIndexes[index] = gSeedTextures[it.value()].id;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
void Context::ParseItemLocationsJson(nlohmann::json spoilerFileJson) {
|
||||
nlohmann::json locationsJson = spoilerFileJson["locations"];
|
||||
for (auto it = locationsJson.begin(); it != locationsJson.end(); ++it) {
|
||||
RandomizerCheck rc = mSpoilerfileCheckNameToEnum[it.key()];
|
||||
if (it->is_structured()) {
|
||||
nlohmann::json itemJson = *it;
|
||||
for (auto itemit = itemJson.begin(); itemit != itemJson.end(); ++itemit) {
|
||||
if (itemit.key() == "item") {
|
||||
itemLocationTable[rc].SetPlacedItem(mSpoilerfileGetNameToEnum[itemit.value().template get<std::string>()]);
|
||||
} else if (itemit.key() == "price") {
|
||||
itemLocationTable[rc].SetCustomPrice(itemit.value().template get<uint16_t>());
|
||||
} else if (itemit.key() == "model") {
|
||||
overrides[rc] = ItemOverride(rc, mSpoilerfileGetNameToEnum[itemit.value().template get<std::string>()]);
|
||||
} else if (itemit.key() == "trickName") {
|
||||
overrides[rc].SetTrickName(Text(itemit.value().template get<std::string>()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
itemLocationTable[rc].SetPlacedItem(mSpoilerfileGetNameToEnum[it.value().template get<std::string>()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string AltarIconString(char iconChar) {
|
||||
std::string iconString = "";
|
||||
switch (iconChar) {
|
||||
case '0':
|
||||
// Kokiri Emerald
|
||||
iconString += 0x13;
|
||||
iconString += 0x6C;
|
||||
break;
|
||||
case '1':
|
||||
// Goron Ruby
|
||||
iconString += 0x13;
|
||||
iconString += 0x6D;
|
||||
break;
|
||||
case '2':
|
||||
// Zora Sapphire
|
||||
iconString += 0x13;
|
||||
iconString += 0x6E;
|
||||
break;
|
||||
case '3':
|
||||
// Forest Medallion
|
||||
iconString += 0x13;
|
||||
iconString += 0x66;
|
||||
break;
|
||||
case '4':
|
||||
// Fire Medallion
|
||||
iconString += 0x13;
|
||||
iconString += 0x67;
|
||||
break;
|
||||
case '5':
|
||||
// Water Medallion
|
||||
iconString += 0x13;
|
||||
iconString += 0x68;
|
||||
break;
|
||||
case '6':
|
||||
// Spirit Medallion
|
||||
iconString += 0x13;
|
||||
iconString += 0x69;
|
||||
break;
|
||||
case '7':
|
||||
// Shadow Medallion
|
||||
iconString += 0x13;
|
||||
iconString += 0x6A;
|
||||
break;
|
||||
case '8':
|
||||
// Light Medallion
|
||||
iconString += 0x13;
|
||||
iconString += 0x6B;
|
||||
break;
|
||||
case 'o':
|
||||
// Open DOT (master sword)
|
||||
iconString += 0x13;
|
||||
iconString += 0x3C;
|
||||
break;
|
||||
case 'c':
|
||||
// Closed DOT (fairy ocarina)
|
||||
iconString += 0x13;
|
||||
iconString += 0x07;
|
||||
break;
|
||||
case 'i':
|
||||
// Intended DOT (oot)
|
||||
iconString += 0x13;
|
||||
iconString += 0x08;
|
||||
break;
|
||||
case 'l':
|
||||
// Light Arrow (for bridge reqs)
|
||||
iconString += 0x13;
|
||||
iconString += 0x12;
|
||||
break;
|
||||
case 'b':
|
||||
// Boss Key (ganon boss key location)
|
||||
iconString += 0x13;
|
||||
iconString += 0x74;
|
||||
break;
|
||||
case 'L':
|
||||
// Bow with Light Arrow
|
||||
iconString += 0x13;
|
||||
iconString += 0x3A;
|
||||
break;
|
||||
case 'k':
|
||||
// Kokiri Tunic
|
||||
iconString += 0x13;
|
||||
iconString += 0x41;
|
||||
break;
|
||||
}
|
||||
return iconString;
|
||||
}
|
||||
|
||||
std::string FormatJsonHintText(std::string jsonHint) {
|
||||
std::string formattedHintMessage = jsonHint;
|
||||
|
||||
// add icons to altar text
|
||||
for (char iconChar : { '0', '1', '2', '3', '4', '5', '6', '7', '8', 'o', 'c', 'i', 'l', 'b', 'L', 'k' }) {
|
||||
std::string textToReplace = "$";
|
||||
textToReplace += iconChar;
|
||||
size_t start_pos = formattedHintMessage.find(textToReplace);
|
||||
if (!(start_pos == std::string::npos)) {
|
||||
std::string iconString = AltarIconString(iconChar);
|
||||
formattedHintMessage.replace(start_pos, textToReplace.length(), iconString);
|
||||
}
|
||||
}
|
||||
return formattedHintMessage;
|
||||
}
|
||||
|
||||
void Context::ParseHintJson(nlohmann::json spoilerFileJson) {
|
||||
// Child Altar
|
||||
std::string childAltarJsonText = spoilerFileJson["childAltar"]["hintText"].template get<std::string>();
|
||||
std::string formattedChildAltarText = FormatJsonHintText(childAltarJsonText);
|
||||
AddHint(RH_ALTAR_CHILD, Text(formattedChildAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
mEmeraldLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["emeraldLoc"]];
|
||||
mRubyLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["rubyLoc"]];
|
||||
mSapphireLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["sapphireLoc"]];
|
||||
// Adult Altar
|
||||
std::string adultAltarJsonText = spoilerFileJson["adultAltar"]["hintText"].template get<std::string>();
|
||||
std::string formattedAdultAltarText = FormatJsonHintText(adultAltarJsonText);
|
||||
AddHint(RH_ALTAR_ADULT, Text(formattedAdultAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
mForestMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["forestMedallionLoc"].template get<std::string>()];
|
||||
mFireMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["fireMedallionLoc"].template get<std::string>()];
|
||||
mWaterMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["waterMedallionLoc"].template get<std::string>()];
|
||||
mShadowMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["shadowMedallionLoc"].template get<std::string>()];
|
||||
mSpiritMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["spiritMedallionLoc"].template get<std::string>()];
|
||||
mLightMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["lightMedallionLoc"].template get<std::string>()];
|
||||
// Ganondorf and Sheik Light Arrow Hints
|
||||
std::string ganonHintText = FormatJsonHintText(spoilerFileJson["ganonHintText"].template get<std::string>());
|
||||
RandomizerCheck lightArrowLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["lightArrowHintLoc"].template get<std::string>()];
|
||||
std::string lightArrowRegion = spoilerFileJson["lightArrowHintRegion"].template get<std::string>();
|
||||
AddHint(RH_GANONDORF_HINT, Text(ganonHintText), lightArrowLoc, HINT_TYPE_STATIC, Text(lightArrowRegion));
|
||||
std::string sheikText = FormatJsonHintText(spoilerFileJson["sheikText"].template get<std::string>());
|
||||
AddHint(RH_SHEIK_LIGHT_ARROWS, Text(sheikText), lightArrowLoc, HINT_TYPE_STATIC, lightArrowRegion);
|
||||
std::string ganonText = FormatJsonHintText(spoilerFileJson["ganonText"].template get<std::string>());
|
||||
AddHint(RH_GANONDORF_NOHINT, Text(ganonText), RC_UNKNOWN_CHECK, HINT_TYPE_JUNK, Text());
|
||||
// Dampe Hookshot Hint
|
||||
std::string dampeText = FormatJsonHintText(spoilerFileJson["dampeText"].template get<std::string>());
|
||||
std::string dampeRegion = spoilerFileJson["dampeRegion"].template get<std::string>();
|
||||
RandomizerCheck dampeHintLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["dampeHintLoc"].template get<std::string>()];
|
||||
AddHint(RH_DAMPES_DIARY, Text(dampeText), dampeHintLoc, HINT_TYPE_STATIC, Text(dampeRegion));
|
||||
// Greg Hint
|
||||
std::string gregText = FormatJsonHintText(spoilerFileJson["gregText"].template get<std::string>());
|
||||
std::string gregRegion = spoilerFileJson["gregRegion"].template get<std::string>();
|
||||
RandomizerCheck gregLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["gregLoc"].template get<std::string>()];
|
||||
AddHint(RH_GREG_RUPEE, Text(gregText), gregLoc, HINT_TYPE_STATIC, Text(gregRegion));
|
||||
// Saria Magic Hint
|
||||
std::string sariaText = FormatJsonHintText(spoilerFileJson["sariaText"].template get<std::string>());
|
||||
std::string sariaRegion = spoilerFileJson["sariaRegion"].template get<std::string>();
|
||||
RandomizerCheck sariaHintLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["sariaHintLoc"].template get<std::string>()];
|
||||
AddHint(RH_SARIA, Text(sariaText), sariaHintLoc, HINT_TYPE_STATIC, Text(sariaRegion));
|
||||
// Warp Songs
|
||||
std::string warpMinuetText = FormatJsonHintText(spoilerFileJson["warpMinuetText"].template get<std::string>());
|
||||
AddHint(RH_MINUET_WARP_LOC, Text(warpMinuetText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpMinuetText));
|
||||
std::string warpBoleroText = FormatJsonHintText(spoilerFileJson["warpBoleroText"].template get<std::string>());
|
||||
AddHint(RH_BOLERO_WARP_LOC, Text(warpBoleroText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpBoleroText));
|
||||
std::string warpSerenadeText = FormatJsonHintText(spoilerFileJson["warpSerenadeText"].template get<std::string>());
|
||||
AddHint(RH_SERENADE_WARP_LOC, Text(warpSerenadeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpSerenadeText));
|
||||
std::string warpRequiemText = FormatJsonHintText(spoilerFileJson["warpRequiemText"].template get<std::string>());
|
||||
AddHint(RH_REQUIEM_WARP_LOC, Text(warpRequiemText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpRequiemText));
|
||||
std::string warpNocturneText = FormatJsonHintText(spoilerFileJson["warpNocturneText"].template get<std::string>());
|
||||
AddHint(RH_NOCTURNE_WARP_LOC, Text(warpNocturneText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpNocturneText));
|
||||
std::string warpPreludeText = FormatJsonHintText(spoilerFileJson["warpPreludeText"].template get<std::string>());
|
||||
AddHint(RH_PRELUDE_WARP_LOC, Text(warpPreludeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpPreludeText));
|
||||
// Gossip Stones
|
||||
nlohmann::json hintsJson = spoilerFileJson["hints"];
|
||||
for (auto it = hintsJson.begin(); it != hintsJson.end(); it++) {
|
||||
RandomizerCheck gossipStoneLoc = mSpoilerfileCheckNameToEnum[it.key()];
|
||||
nlohmann::json hintInfo = it.value();
|
||||
std::string hintText = FormatJsonHintText(hintInfo["hint"].template get<std::string>());
|
||||
HintType hintType = mSpoilerfileHintTypeNameToEnum[hintInfo["type"].template get<std::string>()];
|
||||
RandomizerCheck hintedLocation = mSpoilerfileCheckNameToEnum[hintInfo["location"]];
|
||||
std::string hintedArea = hintInfo["area"].template get<std::string>();
|
||||
AddHint(RandomizerHintKey(gossipStoneLoc - RC_COLOSSUS_GOSSIP_STONE + 1), Text(hintText), hintedLocation, hintType, hintedArea);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Settings> Context::GetSettings() {
|
||||
return mSettings;
|
||||
}
|
||||
|
||||
const std::shared_ptr<EntranceShuffler> Context::GetEntranceShuffler() {
|
||||
return mEntranceShuffler;
|
||||
}
|
||||
|
||||
std::shared_ptr<Dungeons> Context::GetDungeons() {
|
||||
return mDungeons;
|
||||
}
|
||||
|
||||
DungeonInfo* Context::GetDungeon(size_t key) {
|
||||
return mDungeons->GetDungeon(DungeonKey(key));
|
||||
}
|
||||
|
||||
std::shared_ptr<Trials> Context::GetTrials() {
|
||||
return mTrials;
|
||||
}
|
||||
|
||||
TrialInfo* Context::GetTrial(size_t key) {
|
||||
return mTrials->GetTrial(TrialKey(key));
|
||||
}
|
||||
|
||||
Sprite* Context::GetSeedTexture(uint8_t index) {
|
||||
return &gSeedTextures[index];
|
||||
}
|
||||
|
||||
Rando::Option& Context::GetOption(RandomizerSettingKey key) {
|
||||
return mSettings->Setting(key);
|
||||
}
|
||||
|
||||
Rando::Option& Context::GetTrickOption(RandomizerTrick key) {
|
||||
return mSettings->GetTrickOption(key);
|
||||
}
|
||||
} // namespace Rando
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
#include "randomizerTypes.h"
|
||||
#include "item_location.h"
|
||||
#include "item_override.h"
|
||||
#include "3drando/text.hpp"
|
||||
#include "hint.h"
|
||||
|
||||
#include <memory>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
/**
|
||||
* @brief Singleton for storing and accessing dynamic Randomizer-related data
|
||||
@@ -17,6 +20,13 @@
|
||||
* used as a Singleton.
|
||||
*/
|
||||
namespace Rando {
|
||||
class EntranceShuffler;
|
||||
class Settings;
|
||||
class Dungeons;
|
||||
class DungeonInfo;
|
||||
class TrialInfo;
|
||||
class Trials;
|
||||
|
||||
class Context {
|
||||
public:
|
||||
Context();
|
||||
@@ -26,6 +36,7 @@ class Context {
|
||||
void AddHint(RandomizerHintKey hintId, Text text, RandomizerCheck hintedLocation, HintType hintType,
|
||||
Text hintedRegion);
|
||||
ItemLocation* GetItemLocation(RandomizerCheck locKey);
|
||||
ItemLocation* GetItemLocation(size_t locKey);
|
||||
void PlaceItemInLocation(RandomizerCheck locKey, RandomizerGet item, bool applyEffectImmediately = false,
|
||||
bool setHidden = false);
|
||||
std::vector<RandomizerCheck> allLocations;
|
||||
@@ -40,17 +51,58 @@ class Context {
|
||||
void ItemReset();
|
||||
void HintReset();
|
||||
void CreateItemOverrides();
|
||||
std::set<ItemOverride, ItemOverride_Compare> overrides = {};
|
||||
bool IsSeedGenerated();
|
||||
void SetSeedGenerated(bool seedGenerated = true);
|
||||
bool IsSpoilerLoaded();
|
||||
void SetSpoilerLoaded(bool spoilerLoaded = true);
|
||||
bool IsPlandoLoaded();
|
||||
void SetPlandoLoaded(bool plandoLoaded = true);
|
||||
std::shared_ptr<Settings> GetSettings();
|
||||
const std::shared_ptr<EntranceShuffler> GetEntranceShuffler();
|
||||
std::shared_ptr<Dungeons> GetDungeons();
|
||||
DungeonInfo* GetDungeon(size_t key);
|
||||
std::shared_ptr<Trials> GetTrials();
|
||||
TrialInfo* GetTrial(size_t key);
|
||||
Sprite* GetSeedTexture(uint8_t index);
|
||||
Option& GetOption(RandomizerSettingKey key);
|
||||
Option& GetTrickOption(RandomizerTrick key);
|
||||
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
|
||||
void ParseSpoiler(const char* spoilerFileName, bool plandoMode);
|
||||
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
|
||||
void ParseItemLocationsJson(nlohmann::json spoilerFileJson);
|
||||
void ParseHintJson(nlohmann::json spoilerFileJson);
|
||||
std::map<RandomizerCheck, ItemOverride> overrides = {};
|
||||
std::vector<std::vector<RandomizerCheck>> playthroughLocations = {};
|
||||
std::vector<RandomizerCheck> everyPossibleLocation = {};
|
||||
std::vector<RandomizerCheck> wothLocations = {};
|
||||
std::unordered_map<RandomizerCheck, uint8_t> iceTrapModels = {};
|
||||
std::vector<RandomizerGet> possibleIceTrapModels = {};
|
||||
std::unordered_map<RandomizerCheck, RandomizerGet> iceTrapModels = {};
|
||||
std::array<uint8_t, 5> hashIconIndexes = {};
|
||||
std::unordered_map<std::string, RandomizerCheck> mSpoilerfileCheckNameToEnum;
|
||||
bool playthroughBeatable = false;
|
||||
bool allLocationsReachable = false;
|
||||
|
||||
private:
|
||||
static std::weak_ptr<Context> mContext;
|
||||
std::unordered_map<std::string, RandomizerGet> mSpoilerfileGetNameToEnum;
|
||||
std::unordered_map<std::string, HintType> mSpoilerfileHintTypeNameToEnum;
|
||||
std::array<Hint, RH_MAX> hintTable = {};
|
||||
RandomizerCheck mEmeraldLoc;
|
||||
RandomizerCheck mRubyLoc;
|
||||
RandomizerCheck mSapphireLoc;
|
||||
RandomizerCheck mForestMedallionLoc;
|
||||
RandomizerCheck mFireMedallionLoc;
|
||||
RandomizerCheck mWaterMedallionLoc;
|
||||
RandomizerCheck mShadowMedallionLoc;
|
||||
RandomizerCheck mSpiritMedallionLoc;
|
||||
RandomizerCheck mLightMedallionLoc;
|
||||
std::array<ItemLocation, RC_MAX> itemLocationTable = {};
|
||||
std::shared_ptr<Settings> mSettings;
|
||||
std::shared_ptr<EntranceShuffler> mEntranceShuffler;
|
||||
std::shared_ptr<Dungeons> mDungeons;
|
||||
std::shared_ptr<Trials> mTrials;
|
||||
bool mSeedGenerated = false;
|
||||
bool mSpoilerLoaded = false;
|
||||
bool mPlandoLoaded = false;
|
||||
};
|
||||
} // namespace Rando
|
||||
783
soh/soh/Enhancements/randomizer/dungeon.cpp
Normal file
783
soh/soh/Enhancements/randomizer/dungeon.cpp
Normal file
@@ -0,0 +1,783 @@
|
||||
#include "dungeon.h"
|
||||
|
||||
#include "3drando/pool_functions.hpp"
|
||||
#include "static_data.h"
|
||||
#include "context.h"
|
||||
|
||||
namespace Rando {
|
||||
DungeonInfo::DungeonInfo(std::string name_, RandomizerHintTextKey hintKey_, RandomizerGet map_, RandomizerGet compass_,
|
||||
RandomizerGet smallKey_, RandomizerGet keyRing_, RandomizerGet bossKey_,
|
||||
uint8_t vanillaKeyCount_, uint8_t mqKeyCount_, std::vector<RandomizerCheck> vanillaLocations_,
|
||||
std::vector<RandomizerCheck> mqLocations_, std::vector<RandomizerCheck> sharedLocations_,
|
||||
std::vector<RandomizerCheck> bossRoomLocations_)
|
||||
: name(std::move(name_)), hintKey(hintKey_), map(map_), compass(compass_), smallKey(smallKey_), keyRing(keyRing_),
|
||||
bossKey(bossKey_), vanillaKeyCount(vanillaKeyCount_), mqKeyCount(mqKeyCount_),
|
||||
vanillaLocations(std::move(vanillaLocations_)), mqLocations(std::move(mqLocations_)),
|
||||
sharedLocations(std::move(sharedLocations_)), bossRoomLocations(std::move(bossRoomLocations_)) {
|
||||
}
|
||||
DungeonInfo::DungeonInfo() = default;
|
||||
DungeonInfo::~DungeonInfo() = default;
|
||||
|
||||
const std::string& DungeonInfo::GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
void DungeonInfo::SetMQ() {
|
||||
masterQuest = true;
|
||||
}
|
||||
|
||||
void DungeonInfo::ClearMQ() {
|
||||
masterQuest = false;
|
||||
}
|
||||
|
||||
bool DungeonInfo::IsMQ() const {
|
||||
return masterQuest;
|
||||
}
|
||||
|
||||
void DungeonInfo::SetKeyRing() {
|
||||
hasKeyRing = true;
|
||||
}
|
||||
|
||||
void DungeonInfo::ClearKeyRing() {
|
||||
hasKeyRing = false;
|
||||
}
|
||||
|
||||
bool DungeonInfo::HasKeyRing() const {
|
||||
return hasKeyRing;
|
||||
}
|
||||
|
||||
bool DungeonInfo::IsVanilla() const {
|
||||
return !masterQuest;
|
||||
}
|
||||
|
||||
uint8_t DungeonInfo::GetSmallKeyCount() const {
|
||||
return (masterQuest) ? mqKeyCount : vanillaKeyCount;
|
||||
}
|
||||
|
||||
RandomizerHintTextKey DungeonInfo::GetHintKey() const {
|
||||
return hintKey;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetSmallKey() const {
|
||||
return smallKey;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetKeyRing() const {
|
||||
return keyRing;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetMap() const {
|
||||
return map;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetCompass() const {
|
||||
return compass;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetBossKey() const {
|
||||
return bossKey;
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaMap() {
|
||||
if (map == RG_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto mapLocation = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) {
|
||||
return StaticData::GetLocation(loc)->IsCategory(Category::cVanillaMap);
|
||||
})[0];
|
||||
Context::GetInstance()->PlaceItemInLocation(mapLocation, map);
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaCompass() {
|
||||
if (compass == RG_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto compassLocation = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) {
|
||||
return StaticData::GetLocation(loc)->IsCategory(Category::cVanillaCompass);
|
||||
})[0];
|
||||
Context::GetInstance()->PlaceItemInLocation(compassLocation, compass);
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaBossKey() {
|
||||
if (bossKey == RG_NONE || bossKey == RG_GANONS_CASTLE_BOSS_KEY) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto bossKeyLocation = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) {
|
||||
return StaticData::GetLocation(loc)->IsCategory(Category::cVanillaBossKey);
|
||||
})[0];
|
||||
Context::GetInstance()->PlaceItemInLocation(bossKeyLocation, bossKey);
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaSmallKeys() {
|
||||
if (smallKey == RG_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto smallKeyLocations = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) {
|
||||
return StaticData::GetLocation(loc)->IsCategory(Category::cVanillaSmallKey);
|
||||
});
|
||||
for (auto location : smallKeyLocations) {
|
||||
Context::GetInstance()->PlaceItemInLocation(location, smallKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla)
|
||||
std::vector<RandomizerCheck> DungeonInfo::GetDungeonLocations() const {
|
||||
auto locations = masterQuest ? mqLocations : vanillaLocations;
|
||||
AddElementsToPool(locations, sharedLocations);
|
||||
AddElementsToPool(locations, bossRoomLocations);
|
||||
return locations;
|
||||
}
|
||||
|
||||
// Gets all dungeon locations (MQ + Vanilla)
|
||||
std::vector<RandomizerCheck> DungeonInfo::GetEveryLocation() const {
|
||||
auto locations = vanillaLocations;
|
||||
AddElementsToPool(locations, mqLocations);
|
||||
AddElementsToPool(locations, sharedLocations);
|
||||
AddElementsToPool(locations, bossRoomLocations);
|
||||
return locations;
|
||||
}
|
||||
|
||||
Dungeons::Dungeons() {
|
||||
dungeonList[DEKU_TREE] =
|
||||
DungeonInfo("Deku Tree", RHT_DEKU_TREE, RG_DEKU_TREE_MAP, RG_DEKU_TREE_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_DEKU_TREE_MAP_CHEST,
|
||||
RC_DEKU_TREE_COMPASS_CHEST,
|
||||
RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST,
|
||||
RC_DEKU_TREE_BASEMENT_CHEST,
|
||||
RC_DEKU_TREE_SLINGSHOT_CHEST,
|
||||
RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST,
|
||||
RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM,
|
||||
RC_DEKU_TREE_GS_BASEMENT_GATE,
|
||||
RC_DEKU_TREE_GS_BASEMENT_VINES,
|
||||
RC_DEKU_TREE_GS_COMPASS_ROOM,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_DEKU_TREE_MQ_MAP_CHEST,
|
||||
RC_DEKU_TREE_MQ_COMPASS_CHEST,
|
||||
RC_DEKU_TREE_MQ_SLINGSHOT_CHEST,
|
||||
RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST,
|
||||
RC_DEKU_TREE_MQ_BASEMENT_CHEST,
|
||||
RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST,
|
||||
RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST,
|
||||
RC_DEKU_TREE_MQ_DEKU_SCRUB,
|
||||
RC_DEKU_TREE_MQ_GS_LOBBY,
|
||||
RC_DEKU_TREE_MQ_GS_COMPASS_ROOM,
|
||||
RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM,
|
||||
RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_DEKU_TREE_QUEEN_GOHMA_HEART,
|
||||
RC_QUEEN_GOHMA,
|
||||
});
|
||||
dungeonList[DODONGOS_CAVERN] = DungeonInfo("Dodongo's Cavern", RHT_DODONGOS_CAVERN, RG_DODONGOS_CAVERN_MAP,
|
||||
RG_DODONGOS_CAVERN_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_DODONGOS_CAVERN_MAP_CHEST,
|
||||
RC_DODONGOS_CAVERN_COMPASS_CHEST,
|
||||
RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST,
|
||||
RC_DODONGOS_CAVERN_BOMB_BAG_CHEST,
|
||||
RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST,
|
||||
RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY,
|
||||
RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS,
|
||||
RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT,
|
||||
RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT,
|
||||
RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS,
|
||||
RC_DODONGOS_CAVERN_GS_SCARECROW,
|
||||
RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS,
|
||||
RC_DODONGOS_CAVERN_GS_BACK_ROOM,
|
||||
RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_DODONGOS_CAVERN_MQ_MAP_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST,
|
||||
RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR,
|
||||
RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT,
|
||||
RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE,
|
||||
RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS,
|
||||
RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM,
|
||||
RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM,
|
||||
RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM,
|
||||
RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM,
|
||||
RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST,
|
||||
RC_DODONGOS_CAVERN_KING_DODONGO_HEART,
|
||||
RC_KING_DODONGO,
|
||||
});
|
||||
dungeonList[JABU_JABUS_BELLY] = DungeonInfo("Jabu Jabu's Belly", RHT_JABU_JABUS_BELLY, RG_JABU_JABUS_BELLY_MAP,
|
||||
RG_JABU_JABUS_BELLY_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_JABU_JABUS_BELLY_MAP_CHEST,
|
||||
RC_JABU_JABUS_BELLY_COMPASS_CHEST,
|
||||
RC_JABU_JABUS_BELLY_BOOMERANG_CHEST,
|
||||
RC_JABU_JABUS_BELLY_DEKU_SCRUB,
|
||||
RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER,
|
||||
RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER,
|
||||
RC_JABU_JABUS_BELLY_GS_NEAR_BOSS,
|
||||
RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_MAP_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST,
|
||||
RC_JABU_JABUS_BELLY_MQ_COW,
|
||||
RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM,
|
||||
RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM,
|
||||
RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM,
|
||||
RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_JABU_JABUS_BELLY_BARINADE_HEART,
|
||||
RC_BARINADE,
|
||||
});
|
||||
dungeonList[FOREST_TEMPLE] =
|
||||
DungeonInfo("Forest Temple", RHT_FOREST_TEMPLE, RG_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_COMPASS,
|
||||
RG_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_BOSS_KEY, 5, 6,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_FOREST_TEMPLE_FIRST_ROOM_CHEST,
|
||||
RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST,
|
||||
RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST,
|
||||
RC_FOREST_TEMPLE_MAP_CHEST,
|
||||
RC_FOREST_TEMPLE_WELL_CHEST,
|
||||
RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST,
|
||||
RC_FOREST_TEMPLE_EYE_SWITCH_CHEST,
|
||||
RC_FOREST_TEMPLE_BOSS_KEY_CHEST,
|
||||
RC_FOREST_TEMPLE_FLOORMASTER_CHEST,
|
||||
RC_FOREST_TEMPLE_BOW_CHEST,
|
||||
RC_FOREST_TEMPLE_RED_POE_CHEST,
|
||||
RC_FOREST_TEMPLE_BLUE_POE_CHEST,
|
||||
RC_FOREST_TEMPLE_BASEMENT_CHEST,
|
||||
RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD,
|
||||
RC_FOREST_TEMPLE_GS_FIRST_ROOM,
|
||||
RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD,
|
||||
RC_FOREST_TEMPLE_GS_LOBBY,
|
||||
RC_FOREST_TEMPLE_GS_BASEMENT,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_BOW_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_WELL_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_MAP_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_COMPASS_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_REDEAD_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY,
|
||||
RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM,
|
||||
RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD,
|
||||
RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD,
|
||||
RC_FOREST_TEMPLE_MQ_GS_WELL,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_FOREST_TEMPLE_PHANTOM_GANON_HEART,
|
||||
RC_PHANTOM_GANON,
|
||||
});
|
||||
dungeonList[FIRE_TEMPLE] =
|
||||
DungeonInfo("Fire Temple", RHT_FIRE_TEMPLE, RG_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_COMPASS,
|
||||
RG_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_BOSS_KEY, 8, 5,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_FIRE_TEMPLE_NEAR_BOSS_CHEST,
|
||||
RC_FIRE_TEMPLE_FLARE_DANCER_CHEST,
|
||||
RC_FIRE_TEMPLE_BOSS_KEY_CHEST,
|
||||
RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST,
|
||||
RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST,
|
||||
RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST,
|
||||
RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST,
|
||||
RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST,
|
||||
RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST,
|
||||
RC_FIRE_TEMPLE_SCARECROW_CHEST,
|
||||
RC_FIRE_TEMPLE_MAP_CHEST,
|
||||
RC_FIRE_TEMPLE_COMPASS_CHEST,
|
||||
RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST,
|
||||
RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST,
|
||||
RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM,
|
||||
RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP,
|
||||
RC_FIRE_TEMPLE_GS_BOULDER_MAZE,
|
||||
RC_FIRE_TEMPLE_GS_SCARECROW_TOP,
|
||||
RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_COMPASS_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE,
|
||||
RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_MAP_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST,
|
||||
RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY,
|
||||
RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE,
|
||||
RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER,
|
||||
RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR,
|
||||
RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM,
|
||||
RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boos Room Locations
|
||||
RC_FIRE_TEMPLE_VOLVAGIA_HEART,
|
||||
RC_VOLVAGIA,
|
||||
});
|
||||
dungeonList[WATER_TEMPLE] =
|
||||
DungeonInfo("Water Temple", RHT_WATER_TEMPLE, RG_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_COMPASS,
|
||||
RG_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_BOSS_KEY, 6, 2,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_WATER_TEMPLE_MAP_CHEST,
|
||||
RC_WATER_TEMPLE_COMPASS_CHEST,
|
||||
RC_WATER_TEMPLE_TORCHES_CHEST,
|
||||
RC_WATER_TEMPLE_DRAGON_CHEST,
|
||||
RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST,
|
||||
RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST,
|
||||
RC_WATER_TEMPLE_CRACKED_WALL_CHEST,
|
||||
RC_WATER_TEMPLE_BOSS_KEY_CHEST,
|
||||
RC_WATER_TEMPLE_LONGSHOT_CHEST,
|
||||
RC_WATER_TEMPLE_RIVER_CHEST,
|
||||
RC_WATER_TEMPLE_GS_BEHIND_GATE,
|
||||
RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM,
|
||||
RC_WATER_TEMPLE_GS_CENTRAL_PILLAR,
|
||||
RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST,
|
||||
RC_WATER_TEMPLE_GS_RIVER,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST,
|
||||
RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST,
|
||||
RC_WATER_TEMPLE_MQ_COMPASS_CHEST,
|
||||
RC_WATER_TEMPLE_MQ_MAP_CHEST,
|
||||
RC_WATER_TEMPLE_MQ_FREESTANDING_KEY,
|
||||
RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH,
|
||||
RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA,
|
||||
RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY,
|
||||
RC_WATER_TEMPLE_MQ_GS_RIVER,
|
||||
RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_WATER_TEMPLE_MORPHA_HEART,
|
||||
RC_MORPHA,
|
||||
});
|
||||
dungeonList[SPIRIT_TEMPLE] =
|
||||
DungeonInfo("Spirit Temple", RHT_SPIRIT_TEMPLE, RG_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_COMPASS,
|
||||
RG_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_BOSS_KEY, 5, 7,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST,
|
||||
RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST,
|
||||
RC_SPIRIT_TEMPLE_COMPASS_CHEST,
|
||||
RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MAP_CHEST,
|
||||
RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST,
|
||||
RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST,
|
||||
RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST,
|
||||
RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST,
|
||||
RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST,
|
||||
RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST,
|
||||
RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST,
|
||||
RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST,
|
||||
RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST,
|
||||
RC_SPIRIT_TEMPLE_TOPMOST_CHEST,
|
||||
RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM,
|
||||
RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM,
|
||||
RC_SPIRIT_TEMPLE_GS_LOBBY,
|
||||
RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM,
|
||||
RC_SPIRIT_TEMPLE_GS_METAL_FENCE,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_MAP_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM,
|
||||
RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM,
|
||||
RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST,
|
||||
RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH,
|
||||
RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM,
|
||||
},
|
||||
{
|
||||
// Shared Locations
|
||||
RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST,
|
||||
RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST,
|
||||
},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_SPIRIT_TEMPLE_TWINROVA_HEART,
|
||||
RC_TWINROVA,
|
||||
});
|
||||
dungeonList[SHADOW_TEMPLE] =
|
||||
DungeonInfo("Shadow Temple", RHT_SHADOW_TEMPLE, RG_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_COMPASS,
|
||||
RG_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_BOSS_KEY, 5, 6,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_SHADOW_TEMPLE_MAP_CHEST,
|
||||
RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST,
|
||||
RC_SHADOW_TEMPLE_COMPASS_CHEST,
|
||||
RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST,
|
||||
RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST,
|
||||
RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST,
|
||||
RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST,
|
||||
RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST,
|
||||
RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST,
|
||||
RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST,
|
||||
RC_SHADOW_TEMPLE_WIND_HINT_CHEST,
|
||||
RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST,
|
||||
RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST,
|
||||
RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST,
|
||||
RC_SHADOW_TEMPLE_BOSS_KEY_CHEST,
|
||||
RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST,
|
||||
RC_SHADOW_TEMPLE_FREESTANDING_KEY,
|
||||
RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT,
|
||||
RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM,
|
||||
RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT,
|
||||
RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM,
|
||||
RC_SHADOW_TEMPLE_GS_NEAR_SHIP,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_MAP_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST,
|
||||
RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY,
|
||||
RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM,
|
||||
RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM,
|
||||
RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND,
|
||||
RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP,
|
||||
RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS,
|
||||
},
|
||||
{},
|
||||
{
|
||||
// Boss Room Locations
|
||||
RC_SHADOW_TEMPLE_BONGO_BONGO_HEART,
|
||||
RC_BONGO_BONGO,
|
||||
});
|
||||
dungeonList[BOTTOM_OF_THE_WELL] = DungeonInfo(
|
||||
"Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, RG_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_COMPASS,
|
||||
RG_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_KEY_RING, RG_NONE, 3, 2,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_MAP_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY,
|
||||
RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE,
|
||||
RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM,
|
||||
RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM,
|
||||
RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM,
|
||||
},
|
||||
{}, {});
|
||||
dungeonList[ICE_CAVERN] = DungeonInfo("Ice Cavern", RHT_ICE_CAVERN, RG_ICE_CAVERN_MAP, RG_ICE_CAVERN_COMPASS,
|
||||
RG_NONE, RG_NONE, RG_NONE, 0, 0,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_ICE_CAVERN_MAP_CHEST,
|
||||
RC_ICE_CAVERN_COMPASS_CHEST,
|
||||
RC_ICE_CAVERN_IRON_BOOTS_CHEST,
|
||||
RC_ICE_CAVERN_FREESTANDING_POH,
|
||||
RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM,
|
||||
RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM,
|
||||
RC_ICE_CAVERN_GS_HEART_PIECE_ROOM,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST,
|
||||
RC_ICE_CAVERN_MQ_COMPASS_CHEST,
|
||||
RC_ICE_CAVERN_MQ_MAP_CHEST,
|
||||
RC_ICE_CAVERN_MQ_FREESTANDING_POH,
|
||||
RC_ICE_CAVERN_MQ_GS_SCARECROW,
|
||||
RC_ICE_CAVERN_MQ_GS_ICE_BLOCK,
|
||||
RC_ICE_CAVERN_MQ_GS_RED_ICE,
|
||||
},
|
||||
{
|
||||
// Shared Locations
|
||||
RC_SHEIK_IN_ICE_CAVERN,
|
||||
},
|
||||
{});
|
||||
dungeonList[GERUDO_TRAINING_GROUNDS] =
|
||||
DungeonInfo("Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, RG_NONE, RG_NONE,
|
||||
RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, RG_GERUDO_TRAINING_GROUNDS_KEY_RING, RG_NONE, 9, 3,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST,
|
||||
RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST,
|
||||
},
|
||||
{}, {});
|
||||
dungeonList[GANONS_CASTLE] =
|
||||
DungeonInfo("Ganon's Castle", RHT_GANONS_CASTLE, RG_NONE, RG_NONE, RG_GANONS_CASTLE_SMALL_KEY,
|
||||
RG_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_BOSS_KEY, 2, 3,
|
||||
{
|
||||
// Vanilla Locations
|
||||
RC_GANONS_CASTLE_FOREST_TRIAL_CHEST,
|
||||
RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST,
|
||||
RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST,
|
||||
RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST,
|
||||
RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST,
|
||||
RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST,
|
||||
RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST,
|
||||
RC_GANONS_CASTLE_DEKU_SCRUB_LEFT,
|
||||
RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT,
|
||||
RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT,
|
||||
RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT,
|
||||
},
|
||||
{
|
||||
// MQ Locations
|
||||
RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST,
|
||||
RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY,
|
||||
RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT,
|
||||
RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT,
|
||||
RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER,
|
||||
RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT,
|
||||
RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT,
|
||||
},
|
||||
{
|
||||
// Shared Locations
|
||||
RC_GANONS_TOWER_BOSS_KEY_CHEST,
|
||||
RC_GANON,
|
||||
},
|
||||
{});
|
||||
}
|
||||
|
||||
Dungeons::~Dungeons() = default;
|
||||
|
||||
DungeonInfo* Dungeons::GetDungeon(DungeonKey key) {
|
||||
return &dungeonList[key];
|
||||
}
|
||||
|
||||
DungeonInfo* Dungeons::GetDungeonFromScene(uint16_t scene) {
|
||||
switch (scene) {
|
||||
case SCENE_DEKU_TREE:
|
||||
return &dungeonList[DEKU_TREE];
|
||||
case SCENE_DODONGOS_CAVERN:
|
||||
return &dungeonList[DODONGOS_CAVERN];
|
||||
case SCENE_JABU_JABU:
|
||||
return &dungeonList[JABU_JABUS_BELLY];
|
||||
case SCENE_FOREST_TEMPLE:
|
||||
return &dungeonList[FOREST_TEMPLE];
|
||||
case SCENE_FIRE_TEMPLE:
|
||||
return &dungeonList[FIRE_TEMPLE];
|
||||
case SCENE_WATER_TEMPLE:
|
||||
return &dungeonList[WATER_TEMPLE];
|
||||
case SCENE_SPIRIT_TEMPLE:
|
||||
return &dungeonList[SPIRIT_TEMPLE];
|
||||
case SCENE_SHADOW_TEMPLE:
|
||||
return &dungeonList[SHADOW_TEMPLE];
|
||||
case SCENE_BOTTOM_OF_THE_WELL:
|
||||
return &dungeonList[BOTTOM_OF_THE_WELL];
|
||||
case SCENE_ICE_CAVERN:
|
||||
return &dungeonList[ICE_CAVERN];
|
||||
case SCENE_GERUDO_TRAINING_GROUND:
|
||||
return &dungeonList[GERUDO_TRAINING_GROUNDS];
|
||||
case SCENE_INSIDE_GANONS_CASTLE:
|
||||
return &dungeonList[GANONS_CASTLE];
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
size_t Dungeons::CountMQ() {
|
||||
size_t count = 0;
|
||||
for (DungeonInfo& dungeon : dungeonList) {
|
||||
if (dungeon.IsMQ()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void Dungeons::ClearAllMQ() {
|
||||
for (DungeonInfo& dungeon : dungeonList) {
|
||||
dungeon.ClearMQ();
|
||||
}
|
||||
}
|
||||
|
||||
std::array<DungeonInfo*, 12> Dungeons::GetDungeonList() {
|
||||
std::array<DungeonInfo*, 12> dungeonList_;
|
||||
for (size_t i = 0; i < dungeonList.size(); i++) {
|
||||
dungeonList_[i] = &dungeonList[i];
|
||||
}
|
||||
return dungeonList_;
|
||||
}
|
||||
|
||||
size_t Dungeons::GetDungeonListSize() {
|
||||
return dungeonList.size();
|
||||
}
|
||||
void Dungeons::ParseJson(nlohmann::json spoilerFileJson) {
|
||||
try {
|
||||
nlohmann::json mqDungeonsJson = spoilerFileJson["masterQuestDungeons"];
|
||||
for (auto it = mqDungeonsJson.begin(); it != mqDungeonsJson.end(); it++) {
|
||||
std::string dungeonName = it.value().template get<std::string>();
|
||||
for (auto& dungeon : dungeonList) {
|
||||
if (dungeon.GetName() == dungeonName) {
|
||||
dungeon.SetMQ();
|
||||
} else {
|
||||
dungeon.ClearMQ();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} // namespace Rando
|
||||
96
soh/soh/Enhancements/randomizer/dungeon.h
Normal file
96
soh/soh/Enhancements/randomizer/dungeon.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include "randomizerTypes.h"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace Rando {
|
||||
class DungeonInfo {
|
||||
public:
|
||||
DungeonInfo(std::string name_, RandomizerHintTextKey hintKey_, RandomizerGet map_, RandomizerGet compass_,
|
||||
RandomizerGet smallKey_, RandomizerGet keyRing_, RandomizerGet bossKey_, uint8_t vanillaKeyCount_,
|
||||
uint8_t mqKeyCount_, std::vector<RandomizerCheck> vanillaLocations_,
|
||||
std::vector<RandomizerCheck> mqLocations_, std::vector<RandomizerCheck> sharedLocations_,
|
||||
std::vector<RandomizerCheck> bossRoomLocations_);
|
||||
DungeonInfo();
|
||||
~DungeonInfo();
|
||||
|
||||
const std::string& GetName() const;
|
||||
void SetMQ();
|
||||
void ClearMQ();
|
||||
bool IsMQ() const;
|
||||
void SetKeyRing();
|
||||
void ClearKeyRing();
|
||||
bool HasKeyRing() const;
|
||||
bool IsVanilla() const;
|
||||
uint8_t GetSmallKeyCount() const;
|
||||
RandomizerHintTextKey GetHintKey() const;
|
||||
RandomizerGet GetSmallKey() const;
|
||||
RandomizerGet GetKeyRing() const;
|
||||
RandomizerGet GetMap() const;
|
||||
RandomizerGet GetCompass() const;
|
||||
RandomizerGet GetBossKey() const;
|
||||
void PlaceVanillaMap();
|
||||
void PlaceVanillaCompass();
|
||||
void PlaceVanillaBossKey();
|
||||
void PlaceVanillaSmallKeys();
|
||||
std::vector<RandomizerCheck> GetDungeonLocations() const;
|
||||
std::vector<RandomizerCheck> GetEveryLocation() const;
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
RandomizerHintTextKey hintKey;
|
||||
RandomizerGet map;
|
||||
RandomizerGet compass;
|
||||
RandomizerGet smallKey;
|
||||
RandomizerGet keyRing;
|
||||
RandomizerGet bossKey;
|
||||
uint8_t vanillaKeyCount;
|
||||
uint8_t mqKeyCount;
|
||||
bool masterQuest = false;
|
||||
bool hasKeyRing = false;
|
||||
std::vector<RandomizerCheck> vanillaLocations;
|
||||
std::vector<RandomizerCheck> mqLocations;
|
||||
std::vector<RandomizerCheck> sharedLocations;
|
||||
std::vector<RandomizerCheck> bossRoomLocations;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
DEKU_TREE,
|
||||
DODONGOS_CAVERN,
|
||||
JABU_JABUS_BELLY,
|
||||
FOREST_TEMPLE,
|
||||
FIRE_TEMPLE,
|
||||
WATER_TEMPLE,
|
||||
SPIRIT_TEMPLE,
|
||||
SHADOW_TEMPLE,
|
||||
BOTTOM_OF_THE_WELL,
|
||||
ICE_CAVERN,
|
||||
GERUDO_TRAINING_GROUNDS,
|
||||
GANONS_CASTLE
|
||||
} DungeonKey;
|
||||
|
||||
class Dungeons {
|
||||
public:
|
||||
Dungeons();
|
||||
~Dungeons();
|
||||
DungeonInfo* GetDungeon(DungeonKey key);
|
||||
DungeonInfo* GetDungeonFromScene(uint16_t scene);
|
||||
size_t CountMQ();
|
||||
void ClearAllMQ();
|
||||
/// @brief Returns a new array of pointers to the DungeonInfo entries.
|
||||
/// It returns an array of pointers rather than a pointer to an array so that
|
||||
/// this new array can be shuffled for the purposes of randomizing MQ dungeons.
|
||||
/// If you want an individual DungeonInfo entry you should use the GetDungeon
|
||||
/// function from either here or the Context class.
|
||||
/// @return
|
||||
std::array<DungeonInfo*, 12> GetDungeonList();
|
||||
size_t GetDungeonListSize();
|
||||
void ParseJson(nlohmann::json spoilerFileJson);
|
||||
private:
|
||||
std::array<DungeonInfo, 12> dungeonList;
|
||||
};
|
||||
}
|
||||
1597
soh/soh/Enhancements/randomizer/entrance.cpp
Normal file
1597
soh/soh/Enhancements/randomizer/entrance.cpp
Normal file
File diff suppressed because it is too large
Load Diff
151
soh/soh/Enhancements/randomizer/entrance.h
Normal file
151
soh/soh/Enhancements/randomizer/entrance.h
Normal file
@@ -0,0 +1,151 @@
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "randomizerTypes.h"
|
||||
#include "3drando/location_access.hpp"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#define ENTRANCE_SHUFFLE_SUCCESS 0
|
||||
#define ENTRANCE_SHUFFLE_FAILURE 1
|
||||
|
||||
namespace Rando {
|
||||
enum class EntranceType {
|
||||
None,
|
||||
OwlDrop,
|
||||
Spawn,
|
||||
WarpSong,
|
||||
Dungeon,
|
||||
GanonDungeon,
|
||||
DungeonReverse,
|
||||
Boss,
|
||||
ChildBoss,
|
||||
AdultBoss,
|
||||
Interior,
|
||||
InteriorReverse,
|
||||
SpecialInterior,
|
||||
GrottoGrave,
|
||||
GrottoGraveReverse,
|
||||
Overworld,
|
||||
Extra,
|
||||
Mixed,
|
||||
All,
|
||||
};
|
||||
|
||||
class Entrance {
|
||||
public:
|
||||
Entrance(RandomizerRegion connectedRegion_, std::vector<ConditionFn> conditions_met_);
|
||||
void SetCondition(ConditionFn newCondition);
|
||||
bool GetConditionsMet() const;
|
||||
std::string to_string() const;
|
||||
void SetName(std::string name_ = "");
|
||||
std::string GetName() const;
|
||||
void printAgeTimeAccess();
|
||||
bool ConditionsMet(bool allAgeTimes = false) const;
|
||||
uint32_t Getuint32_t() const;
|
||||
bool CheckConditionAtAgeTime(bool& age, bool& time, bool passAnyway = false) const;
|
||||
RandomizerRegion GetConnectedRegionKey() const;
|
||||
Area* GetConnectedRegion() const;
|
||||
void SetParentRegion(RandomizerRegion newParent);
|
||||
RandomizerRegion GetParentRegionKey() const;
|
||||
Area* GetParentRegion() const;
|
||||
void SetNewEntrance(RandomizerRegion newRegion);
|
||||
void SetAsShuffled();
|
||||
bool IsShuffled() const;
|
||||
bool IsAddedToPool() const;
|
||||
void AddToPool();
|
||||
void RemoveFromPool();
|
||||
void SetAsPrimary();
|
||||
bool IsPrimary() const;
|
||||
bool IsDecoupled() const;
|
||||
void SetDecoupled();
|
||||
int16_t GetIndex() const;
|
||||
void SetIndex(int16_t newIndex);
|
||||
int16_t GetBlueWarp() const;
|
||||
void SetBlueWarp(int16_t newBlueWarp);
|
||||
Entrance* GetAssumed() const;
|
||||
void SetReplacement(Entrance* newReplacement);
|
||||
Entrance* GetReplacement() const;
|
||||
EntranceType GetType() const;
|
||||
void SetType(EntranceType newType);
|
||||
Entrance* GetReverse() const;
|
||||
void Connect(RandomizerRegion newConnectedRegion);
|
||||
RandomizerRegion Disconnect();
|
||||
void BindTwoWay(Entrance* otherEntrance);
|
||||
Entrance* GetNewTarget();
|
||||
Entrance* AssumeReachable();
|
||||
|
||||
private:
|
||||
RandomizerRegion parentRegion;
|
||||
RandomizerRegion connectedRegion;
|
||||
std::vector<ConditionFn> conditions_met;
|
||||
|
||||
EntranceType type = EntranceType::None;
|
||||
Entrance* target = nullptr;
|
||||
Entrance* reverse = nullptr;
|
||||
Entrance* assumed = nullptr;
|
||||
Entrance* replacement = nullptr;
|
||||
int16_t index = 0xFFFF;
|
||||
int16_t blueWarp = 0;
|
||||
bool shuffled = false;
|
||||
bool primary = false;
|
||||
bool addedToPool = false;
|
||||
bool decoupled = false;
|
||||
std::string name = "";
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
EntranceType type;
|
||||
RandomizerRegion parentRegion;
|
||||
RandomizerRegion connectedRegion;
|
||||
int16_t index;
|
||||
int16_t blueWarp;
|
||||
} EntranceLinkInfo;
|
||||
|
||||
typedef struct {
|
||||
std::list<RandomizerRegion> targetRegions;
|
||||
std::list<EntranceType> allowedTypes;
|
||||
} PriorityEntrance;
|
||||
// primary, secondary
|
||||
using EntranceInfoPair = std::pair<EntranceLinkInfo, EntranceLinkInfo>;
|
||||
using EntrancePair = std::pair<Entrance*, Entrance*>;
|
||||
using EntrancePools = std::map<EntranceType, std::vector<Entrance*>>;
|
||||
|
||||
class EntranceShuffler {
|
||||
public:
|
||||
std::array<EntranceOverride, ENTRANCE_OVERRIDES_MAX_COUNT> entranceOverrides;
|
||||
std::vector<std::list<Entrance*>> playthroughEntrances;
|
||||
bool HasNoRandomEntrances();
|
||||
void SetNoRandomEntrances(bool noRandomEntrances);
|
||||
int ShuffleAllEntrances();
|
||||
void CreateEntranceOverrides();
|
||||
void UnshuffleAllEntrances();
|
||||
void ParseJson(nlohmann::json spoilerFileJson);
|
||||
private:
|
||||
std::vector<Entrance*> AssumeEntrancePool(std::vector<Entrance*>& entrancePool);
|
||||
bool ShuffleOneWayPriorityEntrances(std::map<std::string, PriorityEntrance>& oneWayPriorities,
|
||||
EntrancePools oneWayEntrancePools, EntrancePools oneWayTargetEntrancePools,
|
||||
int retryCount = 2);
|
||||
bool PlaceOneWayPriorityEntrance(std::string priorityName, std::list<RandomizerRegion>& allowedRegions,
|
||||
std::list<EntranceType>& allowedTypes, std::vector<EntrancePair>& rollbacks,
|
||||
EntrancePools oneWayEntrancePools, EntrancePools oneWayTargetEntrancePools);
|
||||
bool ReplaceEntrance(Entrance* entrance, Entrance* target, std::vector<EntrancePair>& rollbacks);
|
||||
void ShuffleEntrancePool(std::vector<Entrance*>& entrancePool, std::vector<Entrance*>& targetEntrances,
|
||||
int retryCount = 20);
|
||||
bool ShuffleEntrances(std::vector<Entrance*>& entrances, std::vector<Entrance*>& targetEntrances,
|
||||
std::vector<EntrancePair>& rollbacks);
|
||||
bool PlaceOtherImpasHouseEntrance(std::vector<Entrance*> entrances, std::vector<Entrance*> targetEntrances,
|
||||
std::vector<EntrancePair>& rollbacks);
|
||||
bool mNoRandomEntrances;
|
||||
int mTotalRandomizableEntrances = 0;
|
||||
int mCurNumRandomizedEntrances = 0;
|
||||
bool mEntranceShuffleFailure = false;
|
||||
};
|
||||
} // namespace Rando
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
EntranceOverride* Randomizer_GetEntranceOverrides();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "hint.h"
|
||||
|
||||
namespace Rando {
|
||||
Hint::Hint() {}
|
||||
Hint::Hint() : text(std::move(Text())) {}
|
||||
Hint::Hint(Text text_): text(std::move(text_)) {}
|
||||
Hint::Hint(Text text_, RandomizerCheck hintedLocation_, HintType hintType_, Text hintedRegion_)
|
||||
: text(std::move(text_)), hintedLocation(hintedLocation_), hintType(hintType_),
|
||||
@@ -36,6 +36,10 @@ std::string Hint::GetHintedRegion() {
|
||||
return hintedRegion.GetEnglish();
|
||||
}
|
||||
|
||||
const Text& Hint::GetHintedRegionText() {
|
||||
return hintedRegion;
|
||||
};
|
||||
|
||||
void Hint::ResetVariables() {
|
||||
hintedLocation = RC_UNKNOWN_CHECK;
|
||||
addedToPool = false;
|
||||
|
||||
@@ -15,16 +15,17 @@ class Hint {
|
||||
HintType GetHintType();
|
||||
void SetHintType (HintType type);
|
||||
std::string GetHintedRegion();
|
||||
const Text& GetHintedRegionText();
|
||||
void SetHintedRegion (Text region);
|
||||
void ResetVariables();
|
||||
bool IsAddedToPool();
|
||||
void AddToPool();
|
||||
|
||||
private:
|
||||
Text text;
|
||||
RandomizerCheck hintedLocation;
|
||||
HintType hintType;
|
||||
Text hintedRegion;
|
||||
bool addedToPool;
|
||||
Text text = Text();
|
||||
RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK;
|
||||
HintType hintType = HINT_TYPE_STATIC;
|
||||
Text hintedRegion = Text();
|
||||
bool addedToPool = false;
|
||||
};
|
||||
}
|
||||
@@ -83,29 +83,6 @@ void Item::UndoEffect() {
|
||||
Logic::UpdateHelpers();
|
||||
}
|
||||
|
||||
Rando::ItemOverride_Value Item::Value() const {
|
||||
Rando::ItemOverride_Value val;
|
||||
|
||||
val.all = 0;
|
||||
val.itemId = getItemId;
|
||||
if (getItemId == RG_ICE_TRAP) {
|
||||
val.looksLikeItemId = RandomElement(IceTrapModels);
|
||||
}
|
||||
if ((getItemId >= 0x95 && getItemId <= 0x9A)) { // Boss keys
|
||||
val.looksLikeItemId = GI_KEY_BOSS;
|
||||
}
|
||||
if ((getItemId >= 0xAF && getItemId <= 0xB7)) { // Small keys
|
||||
val.looksLikeItemId = GI_KEY_SMALL;
|
||||
}
|
||||
if (type == ITEMTYPE_SHOP) {
|
||||
// With the current shopsanity implementation, we need a way to detect
|
||||
// regular shop items. This method should have no unintended side effects
|
||||
// unless there was a multiworld with 256 players... so, it should be fine.
|
||||
val.player = 0xFF;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
const Text& Item::GetName() const {
|
||||
return name;
|
||||
}
|
||||
@@ -286,7 +263,7 @@ std::shared_ptr<GetItemEntry> Item::GetGIEntry() const {
|
||||
return Rando::StaticData::RetrieveItem(actual).GetGIEntry();
|
||||
}
|
||||
|
||||
GetItemEntry Item::GetGIEntry_Copy() {
|
||||
GetItemEntry Item::GetGIEntry_Copy() const {
|
||||
return *GetGIEntry();
|
||||
}
|
||||
|
||||
@@ -313,9 +290,9 @@ bool Item::IsBottleItem() const {
|
||||
}
|
||||
|
||||
bool Item::IsMajorItem() const {
|
||||
using namespace Settings;
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (type == ITEMTYPE_TOKEN) {
|
||||
return Bridge.Is(RAINBOWBRIDGE_TOKENS) || LACSCondition == LACSCONDITION_TOKENS;
|
||||
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) || ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS;
|
||||
}
|
||||
|
||||
if (type == ITEMTYPE_DROP || type == ITEMTYPE_EVENT || type == ITEMTYPE_SHOP || type == ITEMTYPE_MAP ||
|
||||
@@ -323,12 +300,12 @@ bool Item::IsMajorItem() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == ITEMTYPE_DUNGEONREWARD && (ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON))) {
|
||||
if (type == ITEMTYPE_DUNGEONREWARD && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((randomizerGet == RG_BOMBCHU_5 || randomizerGet == RG_BOMBCHU_10 || randomizerGet == RG_BOMBCHU_20) &&
|
||||
!BombchusInLogic) {
|
||||
!ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -337,25 +314,25 @@ bool Item::IsMajorItem() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == ITEMTYPE_SMALLKEY && (Keysanity.Is(KEYSANITY_VANILLA) || Keysanity.Is(KEYSANITY_OWN_DUNGEON))) {
|
||||
if (type == ITEMTYPE_SMALLKEY && (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == ITEMTYPE_FORTRESS_SMALLKEY && GerudoKeys.Is(GERUDOKEYS_VANILLA)) {
|
||||
if (type == ITEMTYPE_FORTRESS_SMALLKEY && ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_VANILLA)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((type == ITEMTYPE_BOSSKEY && getItemId != 0xAD) &&
|
||||
(BossKeysanity.Is(BOSSKEYSANITY_VANILLA) || BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON))) {
|
||||
(ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA) || ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON))) {
|
||||
return false;
|
||||
}
|
||||
// Ganons Castle Boss Key
|
||||
if (getItemId == 0xAD && (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA) || GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON))) {
|
||||
if (getItemId == 0xAD && (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA) || ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (randomizerGet == RG_GREG_RUPEE) {
|
||||
return Bridge.Is(RAINBOWBRIDGE_GREG);
|
||||
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG);
|
||||
}
|
||||
|
||||
return IsAdvancement();
|
||||
|
||||
@@ -5,15 +5,10 @@
|
||||
#include <memory>
|
||||
|
||||
#include "3drando/text.hpp"
|
||||
#include "3drando/settings.hpp"
|
||||
#include "3drando/hint_list.hpp"
|
||||
#include "randomizerTypes.h"
|
||||
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
|
||||
|
||||
namespace Rando {
|
||||
union ItemOverride_Value;
|
||||
}
|
||||
|
||||
enum ItemType {
|
||||
ITEMTYPE_ITEM,
|
||||
ITEMTYPE_MAP,
|
||||
@@ -51,7 +46,6 @@ class Item {
|
||||
void ApplyEffect();
|
||||
void UndoEffect();
|
||||
|
||||
Rando::ItemOverride_Value Value() const;
|
||||
|
||||
const Text& GetName() const;
|
||||
bool IsAdvancement() const;
|
||||
@@ -60,7 +54,7 @@ class Item {
|
||||
RandomizerGet GetRandomizerGet();
|
||||
uint16_t GetPrice() const;
|
||||
std::shared_ptr<GetItemEntry> GetGIEntry() const;
|
||||
GetItemEntry GetGIEntry_Copy();
|
||||
GetItemEntry GetGIEntry_Copy() const;
|
||||
void SetPrice(uint16_t price_);
|
||||
void SetAsPlaythrough();
|
||||
void SetCustomDrawFunc(CustomDrawFunc);
|
||||
|
||||
@@ -145,7 +145,7 @@ void Rando::StaticData::InitItemTable() {
|
||||
itemTable[RG_GERUDO_FORTRESS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
|
||||
itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Ganons Schloss Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB7, true, &Logic::GanonsCastleKeys, RHT_GANONS_CASTLE_SMALL_KEY,RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
|
||||
itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
|
||||
itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Truhenspiel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xDE, true, &Logic::TreasureGameKeys, RHT_TREASURE_GAME_SMALL_KEY,RG_TREASURE_GAME_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
|
||||
itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Truhenspiel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, &Logic::TreasureGameKeys, RHT_TREASURE_GAME_SMALL_KEY,ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE);
|
||||
// Key Rings
|
||||
itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Waldtempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD5, true, &Logic::ForestTempleKeys, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
|
||||
itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "item_location.h"
|
||||
#include "context.h"
|
||||
|
||||
namespace Rando {
|
||||
ItemLocation::ItemLocation(RandomizerCheck rc_) : rc(rc_) {}
|
||||
@@ -23,6 +24,10 @@ const Item& ItemLocation::GetPlacedItem() const {
|
||||
return Rando::StaticData::RetrieveItem(placedItem);
|
||||
}
|
||||
|
||||
RandomizerGet& ItemLocation::RefPlacedItem() {
|
||||
return placedItem;
|
||||
}
|
||||
|
||||
const Text& ItemLocation::GetPlacedItemName() const {
|
||||
return Rando::StaticData::RetrieveItem(placedItem).GetName();
|
||||
}
|
||||
@@ -69,28 +74,19 @@ uint16_t ItemLocation::GetPrice() const {
|
||||
}
|
||||
|
||||
void ItemLocation::SetPrice(uint16_t price_) {
|
||||
if (hasShopsanityPrice || hasScrubsanityPrice) {
|
||||
if (hasCustomPrice) {
|
||||
return;
|
||||
}
|
||||
price = price_;
|
||||
}
|
||||
|
||||
bool ItemLocation::HasShopsanityPrice() const {
|
||||
return hasShopsanityPrice;
|
||||
bool ItemLocation::HasCustomPrice() const {
|
||||
return hasCustomPrice;
|
||||
}
|
||||
|
||||
void ItemLocation::SetShopsanityPrice(uint16_t price_) {
|
||||
void ItemLocation::SetCustomPrice(uint16_t price_) {
|
||||
price = price_;
|
||||
hasShopsanityPrice = true;
|
||||
}
|
||||
|
||||
bool ItemLocation::HasScrubsanityPrice() const {
|
||||
return hasScrubsanityPrice;
|
||||
}
|
||||
|
||||
void ItemLocation::SetScrubsanityPrice(uint16_t price_) {
|
||||
price = price_;
|
||||
hasScrubsanityPrice = true;
|
||||
hasCustomPrice = true;
|
||||
}
|
||||
|
||||
bool ItemLocation::IsHintable() const {
|
||||
@@ -129,31 +125,31 @@ bool ItemLocation::IsExcluded() const {
|
||||
return excludedOption.Value<bool>();
|
||||
}
|
||||
|
||||
Option* ItemLocation::GetExcludedOption() {
|
||||
Rando::Option* ItemLocation::GetExcludedOption() {
|
||||
return &excludedOption;
|
||||
}
|
||||
|
||||
void ItemLocation::AddExcludeOption() {
|
||||
const std::string name = StaticData::GetLocation(rc)->GetName();
|
||||
if (name.length() < 23) {
|
||||
excludedOption = Option::Bool(name, {"Include", "Exclude"});
|
||||
excludedOption = Rando::Option::Bool(name, {"Include", "Exclude"});
|
||||
} else {
|
||||
size_t lastSpace = name.rfind(' ', 23);
|
||||
std::string settingText = name;
|
||||
settingText.replace(lastSpace, 1, "\n ");
|
||||
|
||||
excludedOption = Option::Bool(settingText, {"Include", "Exclude"});
|
||||
excludedOption = Rando::Option::Bool(settingText, {"Include", "Exclude"});
|
||||
}
|
||||
// RANDOTODO: this without string compares and loops
|
||||
bool alreadyAdded = false;
|
||||
Rando::Location* loc = StaticData::GetLocation(rc);
|
||||
for (const Option* location : Settings::excludeLocationsOptionsVector[loc->GetCollectionCheckGroup()]) {
|
||||
for (const Rando::Option* location : Rando::Context::GetInstance()->GetSettings()->GetExcludeOptionsForGroup(loc->GetCollectionCheckGroup())) {
|
||||
if (location->GetName() == excludedOption.GetName()) {
|
||||
alreadyAdded = true;
|
||||
}
|
||||
}
|
||||
if (!alreadyAdded) {
|
||||
Settings::excludeLocationsOptionsVector[loc->GetCollectionCheckGroup()].push_back(&excludedOption);
|
||||
Rando::Context::GetInstance()->GetSettings()->GetExcludeOptionsForGroup(loc->GetCollectionCheckGroup()).push_back(&excludedOption);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,15 +161,6 @@ void ItemLocation::SetVisible(bool visibleInImGui_) {
|
||||
|
||||
}
|
||||
|
||||
ItemOverride_Key ItemLocation::Key() const {
|
||||
ItemOverride_Key key;
|
||||
key.all = 0;
|
||||
|
||||
key.scene = Rando::StaticData::GetLocation(rc)->GetScene();
|
||||
key.type = static_cast<uint8_t>(StaticData::GetLocation(rc)->GetLocationType()); // TODO make sure these match up
|
||||
return key;
|
||||
}
|
||||
|
||||
void ItemLocation::ResetVariables() {
|
||||
addedToPool = false;
|
||||
placedItem = RG_NONE;
|
||||
@@ -182,8 +169,7 @@ void ItemLocation::ResetVariables() {
|
||||
hintedAt = false;
|
||||
hintedBy = RH_NONE;
|
||||
price = 0;
|
||||
hasShopsanityPrice = false;
|
||||
hasScrubsanityPrice = false;
|
||||
hasCustomPrice = false;
|
||||
hidden = false;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "randomizerTypes.h"
|
||||
#include "item.h"
|
||||
#include "3drando/text.hpp"
|
||||
#include "static_data.h"
|
||||
#include "settings.h"
|
||||
|
||||
namespace Rando {
|
||||
enum ItemOverride_Type {
|
||||
OVR_BASE_ITEM = 0,
|
||||
OVR_CHEST = 1,
|
||||
OVR_COLLECTABLE = 2,
|
||||
OVR_SKULL = 3,
|
||||
OVR_GROTTO_SCRUB = 4,
|
||||
OVR_DELAYED = 5,
|
||||
OVR_TEMPLE = 6,
|
||||
};
|
||||
|
||||
typedef union ItemOverride_Key {
|
||||
uint32_t all;
|
||||
struct {
|
||||
char pad_;
|
||||
uint8_t scene;
|
||||
uint8_t type;
|
||||
};
|
||||
} ItemOverride_Key;
|
||||
|
||||
typedef union ItemOverride_Value {
|
||||
uint32_t all;
|
||||
struct {
|
||||
uint16_t itemId;
|
||||
uint8_t player;
|
||||
uint8_t looksLikeItemId;
|
||||
};
|
||||
} ItemOverride_Value;
|
||||
|
||||
typedef struct ItemOverride {
|
||||
ItemOverride_Key key;
|
||||
ItemOverride_Value value;
|
||||
} ItemOverride;
|
||||
|
||||
class ItemOverride_Compare {
|
||||
public:
|
||||
bool operator()(ItemOverride lhs, ItemOverride rhs) const {
|
||||
return lhs.key.all < rhs.key.all;
|
||||
}
|
||||
};
|
||||
|
||||
class ItemLocation {
|
||||
public:
|
||||
ItemLocation() = default;
|
||||
@@ -58,6 +18,7 @@ class ItemLocation {
|
||||
const Text& GetPlacedItemName() const;
|
||||
RandomizerGet GetPlacedRandomizerGet() const;
|
||||
void SetPlacedItem(const RandomizerGet item);
|
||||
RandomizerGet& RefPlacedItem();
|
||||
void SetDelayedItem(const RandomizerGet item);
|
||||
RandomizerRegion GetParentRegionKey() const;
|
||||
void SetParentRegion (RandomizerRegion region);
|
||||
@@ -66,10 +27,8 @@ class ItemLocation {
|
||||
void SaveDelayedItem();
|
||||
uint16_t GetPrice() const;
|
||||
void SetPrice(uint16_t price_);
|
||||
bool HasShopsanityPrice() const;
|
||||
void SetShopsanityPrice(uint16_t price_);
|
||||
bool HasScrubsanityPrice() const;
|
||||
void SetScrubsanityPrice(uint16_t price_);
|
||||
bool HasCustomPrice() const;
|
||||
void SetCustomPrice(uint16_t price_);
|
||||
bool IsHintable() const;
|
||||
void SetAsHintable();
|
||||
bool IsHintedAt() const;
|
||||
@@ -83,7 +42,6 @@ class ItemLocation {
|
||||
void SetHidden(const bool hidden_);
|
||||
bool IsVisible() const;
|
||||
void SetVisible(bool visibleInImGui_);
|
||||
Rando::ItemOverride_Key Key() const;
|
||||
void ResetVariables();
|
||||
|
||||
private:
|
||||
@@ -97,8 +55,7 @@ class ItemLocation {
|
||||
Option excludedOption = Option::Bool(StaticData::GetLocation(rc)->GetName(), {"Include", "Exclude"});
|
||||
uint16_t price = 0;
|
||||
RandomizerRegion parentRegion = RR_NONE;
|
||||
bool hasShopsanityPrice = false;
|
||||
bool hasScrubsanityPrice = false;
|
||||
bool hasCustomPrice = false;
|
||||
bool hidden = false;
|
||||
bool visibleInImGui = false;
|
||||
};
|
||||
|
||||
30
soh/soh/Enhancements/randomizer/item_override.cpp
Normal file
30
soh/soh/Enhancements/randomizer/item_override.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "item_override.h"
|
||||
|
||||
namespace Rando {
|
||||
ItemOverride::ItemOverride(RandomizerCheck location_, RandomizerGet looksLike_)
|
||||
: location(location_), looksLike(looksLike_) {};
|
||||
|
||||
RandomizerCheck ItemOverride::GetLocation() const {
|
||||
return location;
|
||||
}
|
||||
|
||||
void ItemOverride::SetLocation(RandomizerCheck location_) {
|
||||
location = location_;
|
||||
}
|
||||
|
||||
RandomizerGet ItemOverride::LooksLike() const {
|
||||
return looksLike;
|
||||
}
|
||||
|
||||
RandomizerGet& ItemOverride::RefLooksLike() {
|
||||
return looksLike;
|
||||
}
|
||||
|
||||
Text& ItemOverride::GetTrickName() {
|
||||
return trickName;
|
||||
}
|
||||
|
||||
void ItemOverride::SetTrickName(Text trickName_) {
|
||||
trickName = trickName_;
|
||||
}
|
||||
} // namespace Rando
|
||||
23
soh/soh/Enhancements/randomizer/item_override.h
Normal file
23
soh/soh/Enhancements/randomizer/item_override.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "randomizerTypes.h"
|
||||
#include "3drando/text.hpp"
|
||||
|
||||
namespace Rando {
|
||||
/// @brief Class representing overrides of individual items. Used for trick names and models for ice traps.
|
||||
class ItemOverride {
|
||||
public:
|
||||
ItemOverride() = default;
|
||||
ItemOverride(RandomizerCheck location_, RandomizerGet looksLike_);
|
||||
RandomizerCheck GetLocation() const;
|
||||
void SetLocation(RandomizerCheck);
|
||||
RandomizerGet LooksLike() const;
|
||||
RandomizerGet& RefLooksLike();
|
||||
Text& GetTrickName();
|
||||
void SetTrickName (Text trickName);
|
||||
private:
|
||||
RandomizerCheck location;
|
||||
RandomizerGet looksLike;
|
||||
Text trickName;
|
||||
};
|
||||
} // namespace Rando
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "location.h"
|
||||
#include "3drando/hint_list.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
RandomizerCheck Rando::Location::GetRandomizerCheck() const {
|
||||
return rc;
|
||||
|
||||
144
soh/soh/Enhancements/randomizer/option.cpp
Normal file
144
soh/soh/Enhancements/randomizer/option.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "option.h"
|
||||
|
||||
namespace Rando {
|
||||
Option Option::Bool(std::string name_, std::vector<std::string> options_, OptionCategory category_,
|
||||
uint8_t defaultOption_, bool defaultHidden_) {
|
||||
return Option(false, std::move(name_), std::move(options_), category_, defaultOption_, defaultHidden_);
|
||||
}
|
||||
|
||||
Option Option::U8(std::string name_, std::vector<std::string> options_, OptionCategory category_,
|
||||
uint8_t defaultOption_, bool defaultHidden_) {
|
||||
return Option(uint8_t(0), std::move(name_), std::move(options_), category_, defaultOption_, defaultHidden_);
|
||||
}
|
||||
|
||||
Option Option::LogicTrick(std::string name_) {
|
||||
return Option(false, std::move(name_), { "Disabled", "Enabled" }, OptionCategory::Setting, 0, 0);
|
||||
}
|
||||
|
||||
Option::operator bool() const {
|
||||
if (std::holds_alternative<bool>(var)) {
|
||||
return Value<bool>();
|
||||
} else {
|
||||
return Value<uint8_t>() != 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t Option::GetOptionCount() const {
|
||||
return options.size();
|
||||
}
|
||||
|
||||
const std::string& Option::GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
uint8_t Option::GetSelectedOptionIndex() const {
|
||||
return selectedOption;
|
||||
}
|
||||
|
||||
const std::string& Option::GetSelectedOptionText() const {
|
||||
return options[selectedOption];
|
||||
}
|
||||
|
||||
void Option::SetVariable() {
|
||||
if (std::holds_alternative<bool>(var)) {
|
||||
var.emplace<bool>(selectedOption != 0);
|
||||
} else {
|
||||
var.emplace<uint8_t>(selectedOption);
|
||||
}
|
||||
}
|
||||
|
||||
void Option::SetDelayedOption() {
|
||||
delayedOption = selectedOption;
|
||||
}
|
||||
|
||||
void Option::RestoreDelayedOption() {
|
||||
selectedOption = delayedOption;
|
||||
SetVariable();
|
||||
}
|
||||
|
||||
void Option::SetSelectedIndex(size_t idx) {
|
||||
selectedOption = idx;
|
||||
if (selectedOption >= options.size()) {
|
||||
selectedOption = 0;
|
||||
}
|
||||
SetVariable();
|
||||
}
|
||||
|
||||
void Option::Hide() {
|
||||
hidden = true;
|
||||
}
|
||||
|
||||
void Option::Unhide() {
|
||||
hidden = false;
|
||||
}
|
||||
|
||||
bool Option::IsHidden() const {
|
||||
return hidden;
|
||||
}
|
||||
|
||||
bool Option::IsCategory(OptionCategory category) const {
|
||||
return category == this->category;
|
||||
}
|
||||
|
||||
Option::Option(uint8_t var_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
|
||||
uint8_t defaultOption_, bool defaultHidden_)
|
||||
: var(var_), name(std::move(name_)), options(std::move(options_)), category(category_),
|
||||
defaultOption(defaultOption_), defaultHidden(defaultHidden_) {
|
||||
selectedOption = defaultOption;
|
||||
hidden = defaultHidden;
|
||||
SetVariable();
|
||||
}
|
||||
Option::Option(bool var_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
|
||||
uint8_t defaultOption_, bool defaultHidden_)
|
||||
: var(var_), name(std::move(name_)), options(std::move(options_)), category(category_),
|
||||
defaultOption(defaultOption_), defaultHidden(defaultHidden_) {
|
||||
selectedOption = defaultOption;
|
||||
hidden = defaultHidden;
|
||||
SetVariable();
|
||||
}
|
||||
|
||||
OptionGroup::OptionGroup(std::string name, std::vector<Option*> options, OptionGroupType groupType, bool printInSpoiler,
|
||||
OptionGroupType containsType)
|
||||
: mName(std::move(name)), mOptions(std::move(options)), mGroupType(groupType), mPrintInSpoiler(printInSpoiler),
|
||||
mContainsType(containsType) {
|
||||
}
|
||||
|
||||
OptionGroup::OptionGroup(std::string name, std::vector<OptionGroup*> subGroups, OptionGroupType groupType,
|
||||
bool printInSpoiler, OptionGroupType containsType)
|
||||
: mName(std::move(name)), mSubGroups(std::move(subGroups)), mGroupType(groupType), mPrintInSpoiler(printInSpoiler),
|
||||
mContainsType(containsType) {
|
||||
}
|
||||
|
||||
OptionGroup OptionGroup::SubGroup(std::string name, std::vector<Option*> options, bool printInSpoiler) {
|
||||
return OptionGroup(std::move(name), std::move(options), OptionGroupType::SUBGROUP, printInSpoiler);
|
||||
}
|
||||
|
||||
OptionGroup OptionGroup::SubGroup(std::string name, std::vector<OptionGroup*> subGroups, bool printInSpoiler) {
|
||||
return OptionGroup(std::move(name), std::move(subGroups), OptionGroupType::SUBGROUP, printInSpoiler,
|
||||
OptionGroupType::SUBGROUP);
|
||||
}
|
||||
|
||||
const std::string& OptionGroup::GetName() const {
|
||||
return mName;
|
||||
}
|
||||
|
||||
const std::vector<Option*>& OptionGroup::GetOptions() const {
|
||||
return mOptions;
|
||||
}
|
||||
|
||||
const std::vector<OptionGroup*>& OptionGroup::GetSubGroups() const {
|
||||
return mSubGroups;
|
||||
}
|
||||
|
||||
bool OptionGroup::PrintInSpoiler() const {
|
||||
return mPrintInSpoiler;
|
||||
}
|
||||
|
||||
OptionGroupType OptionGroup::GetGroupType() const {
|
||||
return mGroupType;
|
||||
}
|
||||
|
||||
OptionGroupType OptionGroup::GetContainsType() const {
|
||||
return mContainsType;
|
||||
}
|
||||
} // namespace Rando
|
||||
100
soh/soh/Enhancements/randomizer/option.h
Normal file
100
soh/soh/Enhancements/randomizer/option.h
Normal file
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Rando {
|
||||
enum class OptionCategory {
|
||||
Setting,
|
||||
Toggle,
|
||||
};
|
||||
|
||||
class Option {
|
||||
public:
|
||||
Option() = default;
|
||||
static Option Bool(std::string name_, std::vector<std::string> options_ = { "Off", "On" },
|
||||
OptionCategory category_ = OptionCategory::Setting, uint8_t defaultOption_ = 0,
|
||||
bool defaultHidden_ = false);
|
||||
static Option U8(std::string name_, std::vector<std::string> options_,
|
||||
OptionCategory category_ = OptionCategory::Setting, uint8_t defaultOption = 0,
|
||||
bool defaultHidden = false);
|
||||
static Option LogicTrick(std::string name_);
|
||||
|
||||
template <typename T> T Value() const {
|
||||
return std::get<T>(var);
|
||||
}
|
||||
|
||||
template <typename T> bool Is(T other) const {
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "T must be an integral type or an enum.");
|
||||
if constexpr ((std::is_integral_v<T> && !std::is_same_v<bool, T>) || std::is_enum_v<T>) {
|
||||
return Value<uint8_t>() == static_cast<uint8_t>(other);
|
||||
} else {
|
||||
return Value<bool>() == static_cast<bool>(other);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> bool IsNot(T other) const {
|
||||
return !Is(other);
|
||||
}
|
||||
|
||||
explicit operator bool() const;
|
||||
size_t GetOptionCount() const;
|
||||
const std::string& GetName() const;
|
||||
const std::string& GetSelectedOptionText() const;
|
||||
uint8_t GetSelectedOptionIndex() const;
|
||||
void SetVariable();
|
||||
void SetDelayedOption();
|
||||
void RestoreDelayedOption();
|
||||
void SetSelectedIndex(size_t idx);
|
||||
void Hide();
|
||||
void Unhide();
|
||||
bool IsHidden() const;
|
||||
bool IsCategory(OptionCategory category) const;
|
||||
|
||||
private:
|
||||
Option(uint8_t var_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
|
||||
uint8_t defaultOption_, bool defaultHidden_);
|
||||
Option(bool var_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
|
||||
uint8_t defaultOption_, bool defaultHidden_);
|
||||
std::variant<bool, uint8_t> var;
|
||||
std::string name;
|
||||
std::vector<std::string> options;
|
||||
uint8_t selectedOption = 0;
|
||||
uint8_t delayedOption = 0;
|
||||
bool hidden = false;
|
||||
OptionCategory category;
|
||||
uint8_t defaultOption = false;
|
||||
bool defaultHidden = false;
|
||||
};
|
||||
|
||||
enum class OptionGroupType {
|
||||
DEFAULT,
|
||||
SUBGROUP,
|
||||
};
|
||||
|
||||
class OptionGroup {
|
||||
public:
|
||||
OptionGroup() = default;
|
||||
OptionGroup(std::string name, std::vector<Option*> options, OptionGroupType groupType = OptionGroupType::DEFAULT, bool printInSpoiler = true, OptionGroupType containsType = OptionGroupType::DEFAULT);
|
||||
OptionGroup(std::string name, std::vector<OptionGroup*> subGroups, OptionGroupType groupType = OptionGroupType::DEFAULT, bool printInSpoiler = true, OptionGroupType containsType = OptionGroupType::SUBGROUP);
|
||||
static OptionGroup SubGroup(std::string name, std::vector<Option*> options, bool printInSpoiler = true);
|
||||
static OptionGroup SubGroup(std::string name, std::vector<OptionGroup*> subGroups, bool printInSpoiler = true);
|
||||
const std::string& GetName() const;
|
||||
const std::vector<Option*>& GetOptions() const;
|
||||
const std::vector<OptionGroup*>& GetSubGroups() const;
|
||||
bool PrintInSpoiler() const;
|
||||
OptionGroupType GetGroupType() const;
|
||||
OptionGroupType GetContainsType() const;
|
||||
|
||||
private:
|
||||
std::string mName;
|
||||
std::vector<Option*> mOptions;
|
||||
std::vector<OptionGroup*> mSubGroups;
|
||||
OptionGroupType mGroupType = OptionGroupType::DEFAULT;
|
||||
bool mPrintInSpoiler;
|
||||
OptionGroupType mContainsType = OptionGroupType::DEFAULT;
|
||||
};
|
||||
} // namespace Rando
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef RANDOHASH_H
|
||||
#define RANDOHASH_H
|
||||
|
||||
#include "randomizerTypes.h"
|
||||
#include <array>
|
||||
#include "variables.h"
|
||||
@@ -108,4 +111,5 @@ std::array<Sprite, 100> gSeedTextures = { {
|
||||
{ dgQuestIconSmallKeyTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b, 97 },
|
||||
{ dgQuestIconMagicJarSmallTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b, 98 },
|
||||
{ dgQuestIconMagicJarBigTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b, 99 },
|
||||
} };
|
||||
} };
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,24 +22,8 @@
|
||||
|
||||
class Randomizer {
|
||||
private:
|
||||
std::unordered_map<RandomizerCheck, RandomizerGetData> itemLocations;
|
||||
std::unordered_map<RandomizerCheck, std::string> hintLocations;
|
||||
std::string childAltarText;
|
||||
std::string adultAltarText;
|
||||
std::string ganonHintText;
|
||||
std::string ganonText;
|
||||
std::string dampeText;
|
||||
std::string sheikText;
|
||||
std::string sariaText;
|
||||
std::unordered_map<RandomizerSettingKey, u8> randoSettings;
|
||||
void ParseRandomizerSettingsFile(const char* spoilerFileName);
|
||||
void ParseHintLocationsFile(const char* spoilerFileName);
|
||||
void ParseRequiredTrialsFile(const char* spoilerFileName);
|
||||
void ParseMasterQuestDungeonsFile(const char* spoilerFileName);
|
||||
void ParseItemLocationsFile(const char* spoilerFileName, bool silent);
|
||||
void ParseEntranceDataFile(const char* spoilerFileName, bool silent);
|
||||
bool IsItemVanilla(RandomizerGet randoGet);
|
||||
int16_t GetVanillaMerchantPrice(RandomizerCheck check);
|
||||
|
||||
public:
|
||||
Randomizer();
|
||||
@@ -55,37 +39,17 @@ class Randomizer {
|
||||
static const std::string randoMiscHintsTableID;
|
||||
|
||||
// Public for now to be accessed by SaveManager, will be made private again soon :tm:
|
||||
std::unordered_map<RandomizerInf, bool> trialsRequired;
|
||||
std::unordered_set<uint16_t> masterQuestDungeons;
|
||||
std::unordered_map<RandomizerCheck, u16> merchantPrices;
|
||||
std::unordered_map<RandomizerGet, std::array<std::string, 3>> EnumToSpoilerfileGetName;
|
||||
|
||||
static Sprite* GetSeedTexture(uint8_t index);
|
||||
s16 GetItemModelFromId(s16 itemId);
|
||||
s32 GetItemIDFromGetItemID(s32 getItemId);
|
||||
bool SpoilerFileExists(const char* spoilerFileName);
|
||||
void LoadRandomizerSettings(const char* spoilerFileName);
|
||||
void LoadHintLocations(const char* spoilerFileName);
|
||||
void LoadMerchantMessages(const char* spoilerFileName);
|
||||
void LoadItemLocations(const char* spoilerFileName, bool silent);
|
||||
void LoadRequiredTrials(const char* spoilerFileName);
|
||||
void LoadMasterQuestDungeons(const char* spoilerFileName);
|
||||
void LoadMerchantMessages();
|
||||
void LoadHintMessages();
|
||||
bool IsTrialRequired(RandomizerInf trial);
|
||||
void LoadEntranceOverrides(const char* spoilerFileName, bool silent);
|
||||
u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey);
|
||||
RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams);
|
||||
RandomizerCheck GetCheckFromRandomizerInf(RandomizerInf randomizerInf);
|
||||
RandomizerInf GetRandomizerInfFromCheck(RandomizerCheck rc);
|
||||
RandomizerGetData GetRandomizerGetDataFromActor(s16 actorId, s16 sceneNum, s16 actorParams);
|
||||
RandomizerGetData GetRandomizerGetDataFromKnownCheck(RandomizerCheck randomizerCheck);
|
||||
GetItemEntry GetItemEntryFromRGData(RandomizerGetData rgData, GetItemID ogItemId, bool checkObtainability = true);
|
||||
std::string GetChildAltarText() const;
|
||||
std::string GetAdultAltarText() const;
|
||||
std::string GetGanonText() const;
|
||||
std::string GetGanonHintText() const;
|
||||
std::string GetDampeText() const;
|
||||
std::string GetSheikText() const;
|
||||
std::string GetSariaText() const;
|
||||
Rando::Location* GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams);
|
||||
ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
|
||||
ShopItemIdentity IdentifyShopItem(s32 sceneNum, u8 slotIndex);
|
||||
|
||||
@@ -1858,47 +1858,48 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
RH_NONE,
|
||||
RH_DMC_GOSSIP_STONE,
|
||||
RH_DMT_GOSSIP_STONE,
|
||||
RH_COLOSSUS_GOSSIP_STONE,
|
||||
RH_DMC_GOSSIP_STONE,
|
||||
RH_DMC_UPPER_GROTTO_GOSSIP_STONE,
|
||||
RH_DMT_GOSSIP_STONE,
|
||||
RH_DMT_STORMS_GROTTO_GOSSIP_STONE,
|
||||
RH_DODONGOS_CAVERN_GOSSIP_STONE,
|
||||
RH_GV_GOSSIP_STONE,
|
||||
RH_ZF_FAIRY_GOSSIP_STONE,
|
||||
RH_GC_MAZE_GOSSIP_STONE,
|
||||
RH_GC_MEDIGORON_GOSSIP_STONE,
|
||||
RH_GV_GOSSIP_STONE,
|
||||
RH_GRAVEYARD_GOSSIP_STONE,
|
||||
RH_HC_MALON_GOSSIP_STONE,
|
||||
RH_HC_ROCK_WALL_GOSSIP_STONE,
|
||||
RH_HC_STORMS_GROTTO_GOSSIP_STONE,
|
||||
RH_HF_COW_GROTTO_GOSSIP_STONE,
|
||||
RH_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE,
|
||||
RH_HF_OPEN_GROTTO_GOSSIP_STONE,
|
||||
RH_HF_SOUTHEAST_GROTTO_GOSSIP_STONE,
|
||||
RH_ZF_JABU_GOSSIP_STONE,
|
||||
RH_KF_DEKU_TREE_GOSSIP_STONE_LEFT,
|
||||
RH_KF_DEKU_TREE_GOSSIP_STONE_RIGHT,
|
||||
RH_KF_GOSSIP_STONE,
|
||||
RH_KF_STORMS_GROTTO_GOSSIP_STONE,
|
||||
RH_KAK_OPEN_GROTTO_GOSSIP_STONE,
|
||||
RH_LH_LAB_GOSSIP_STONE,
|
||||
RH_LH_GOSSIP_STONE_SOUTHEAST,
|
||||
RH_LH_GOSSIP_STONE_SOUTHWEST,
|
||||
RH_LW_GOSSIP_STONE,
|
||||
RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE,
|
||||
RH_SFM_MAZE_GOSSIP_STONE_LOWER,
|
||||
RH_SFM_MAZE_GOSSIP_STONE_UPPER,
|
||||
RH_SFM_SARIA_GOSSIP_STONE,
|
||||
RH_TOT_GOSSIP_STONE_LEFT,
|
||||
RH_TOT_GOSSIP_STONE_RIGHT,
|
||||
RH_TOT_GOSSIP_STONE_RIGHT_CENTER,
|
||||
RH_TOT_GOSSIP_STONE_LEFT_CENTER,
|
||||
RH_TOT_GOSSIP_STONE_LEFT,
|
||||
RH_TOT_GOSSIP_STONE_RIGHT_CENTER,
|
||||
RH_TOT_GOSSIP_STONE_RIGHT,
|
||||
RH_ZD_GOSSIP_STONE,
|
||||
RH_ZF_FAIRY_GOSSIP_STONE,
|
||||
RH_ZF_JABU_GOSSIP_STONE,
|
||||
RH_ZR_NEAR_GROTTOS_GOSSIP_STONE,
|
||||
RH_ZR_NEAR_DOMAIN_GOSSIP_STONE,
|
||||
RH_HF_COW_GROTTO_GOSSIP_STONE,
|
||||
RH_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE,
|
||||
RH_HF_SOUTHEAST_GROTTO_GOSSIP_STONE,
|
||||
RH_HF_OPEN_GROTTO_GOSSIP_STONE,
|
||||
RH_KAK_OPEN_GROTTO_GOSSIP_STONE,
|
||||
RH_ZR_NEAR_GROTTOS_GOSSIP_STONE,
|
||||
RH_ZR_OPEN_GROTTO_GOSSIP_STONE,
|
||||
RH_KF_STORMS_GROTTO_GOSSIP_STONE,
|
||||
RH_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE,
|
||||
RH_DMT_STORMS_GROTTO_GOSSIP_STONE,
|
||||
RH_DMC_UPPER_GROTTO_GOSSIP_STONE,
|
||||
RH_GANONDORF_HINT,
|
||||
RH_GANONDORF_NOHINT,
|
||||
RH_DAMPES_DIARY,
|
||||
RH_GREG_RUPEE,
|
||||
RH_MEDIGORON,
|
||||
@@ -1906,6 +1907,14 @@ typedef enum {
|
||||
RH_WASTELAND_BOMBCHU_SALESMAN,
|
||||
RH_ALTAR_CHILD,
|
||||
RH_ALTAR_ADULT,
|
||||
RH_SARIA,
|
||||
RH_SHEIK_LIGHT_ARROWS,
|
||||
RH_MINUET_WARP_LOC,
|
||||
RH_BOLERO_WARP_LOC,
|
||||
RH_SERENADE_WARP_LOC,
|
||||
RH_REQUIEM_WARP_LOC,
|
||||
RH_NOCTURNE_WARP_LOC,
|
||||
RH_PRELUDE_WARP_LOC,
|
||||
RH_MAX,
|
||||
} RandomizerHintKey;
|
||||
|
||||
@@ -3242,6 +3251,52 @@ typedef struct {
|
||||
char trickName[MAX_TRICK_NAME_SIZE];
|
||||
} RandomizerGetData;
|
||||
|
||||
typedef enum {
|
||||
RSG_NONE,
|
||||
RSG_LOGIC,
|
||||
RSG_EXCLUDES_KOKIRI_FOREST,
|
||||
RSG_EXCLUDES_LOST_WOODS,
|
||||
RSG_EXCLUDES_DEKU_TREE,
|
||||
RSG_EXCLUDES_FOREST_TEMPLE,
|
||||
RSG_EXCLUDES_KAKARIKO_VILLAGE,
|
||||
RSG_EXCLUDES_BOTTOM_OF_THE_WELL,
|
||||
RSG_EXCLUDES_SHADOW_TEMPLE,
|
||||
RSG_EXCLUDES_DEATH_MOUNTAIN,
|
||||
RSG_EXCLUDES_GORON_CITY,
|
||||
RSG_EXCLUDES_DODONGOS_CAVERN,
|
||||
RSG_EXCLUDES_FIRE_TEMPLE,
|
||||
RSG_EXCLUDES_ZORAS_RIVER,
|
||||
RSG_EXCLUDES_ZORAS_DOMAIN,
|
||||
RSG_EXCLUDES_JABU_JABU,
|
||||
RSG_EXCLUDES_ICE_CAVERN,
|
||||
RSG_EXCLUDES_HYRULE_FIELD,
|
||||
RSG_EXCLUDES_LON_LON_RANCH,
|
||||
RSG_EXCLUDES_LAKE_HYLIA,
|
||||
RSG_EXCLUDES_WATER_TEMPLE,
|
||||
RSG_EXCLUDES_GERUDO_VALLEY,
|
||||
RSG_EXCLUDES_GERUDO_TRAINING_GROUNDS,
|
||||
RSG_EXCLUDES_SPIRIT_TEMPLE,
|
||||
RSG_EXCLUDES_HYRULE_CASTLE,
|
||||
RSG_EXCLUDES_GANONS_CASTLE,
|
||||
RSG_EXCLUDES,
|
||||
RSG_TRICKS,
|
||||
RSG_GLITCHES,
|
||||
RSG_OPEN,
|
||||
RSG_WORLD,
|
||||
RSG_SHUFFLE,
|
||||
RSG_SHUFFLE_DUNGEON_ITEMS,
|
||||
RSG_SHUFFLE_DUNGEON_QUESTS,
|
||||
RSG_DETAILED_LOGIC,
|
||||
RSG_STARTING_ITEMS,
|
||||
RSG_STARTING_SONGS,
|
||||
RSG_STARTING_OTHER,
|
||||
RSG_STARTING_INVENTORY,
|
||||
RSG_TIMESAVERS,
|
||||
RSG_MISC,
|
||||
RSG_ITEM_POOL,
|
||||
RSG_MAX,
|
||||
} RandomizerSettingGroupKey;
|
||||
|
||||
typedef enum {
|
||||
RSK_NONE,
|
||||
RSK_LOGIC_RULES,
|
||||
@@ -3264,6 +3319,7 @@ typedef enum {
|
||||
RSK_SHUFFLE_OCARINA,
|
||||
RSK_STARTING_DEKU_SHIELD,
|
||||
RSK_STARTING_KOKIRI_SWORD,
|
||||
RSK_STARTING_MASTER_SWORD,
|
||||
RSK_STARTING_ZELDAS_LULLABY,
|
||||
RSK_STARTING_EPONAS_SONG,
|
||||
RSK_STARTING_SARIAS_SONG,
|
||||
@@ -3278,7 +3334,6 @@ typedef enum {
|
||||
RSK_STARTING_PRELUDE_OF_LIGHT,
|
||||
RSK_SHUFFLE_KOKIRI_SWORD,
|
||||
RSK_SHUFFLE_MASTER_SWORD,
|
||||
RSK_STARTING_MAPS_COMPASSES,
|
||||
RSK_SHUFFLE_DUNGEON_REWARDS,
|
||||
RSK_SHUFFLE_SONGS,
|
||||
RSK_SHUFFLE_TOKENS,
|
||||
@@ -3308,6 +3363,7 @@ typedef enum {
|
||||
RSK_SCRUB_TEXT_HINT,
|
||||
RSK_HINT_CLARITY,
|
||||
RSK_HINT_DISTRIBUTION,
|
||||
RSK_SHUFFLE_MAPANDCOMPASS,
|
||||
RSK_KEYSANITY,
|
||||
RSK_GERUDO_KEYS,
|
||||
RSK_BOSS_KEYSANITY,
|
||||
@@ -3334,8 +3390,9 @@ typedef enum {
|
||||
RSK_ENABLE_BOMBCHU_DROPS,
|
||||
RSK_BOMBCHUS_IN_LOGIC,
|
||||
RSK_LINKS_POCKET,
|
||||
RSK_RANDOM_MQ_DUNGEONS,
|
||||
RSK_MQ_DUNGEON_RANDOM,
|
||||
RSK_MQ_DUNGEON_COUNT,
|
||||
RSK_MQ_DUNGEON_SET,
|
||||
RSK_MQ_DEKU_TREE,
|
||||
RSK_MQ_DODONGOS_CAVERN,
|
||||
RSK_MQ_JABU_JABU,
|
||||
@@ -3380,6 +3437,8 @@ typedef enum {
|
||||
RSK_MIX_GROTTO_ENTRANCES,
|
||||
RSK_DECOUPLED_ENTRANCES,
|
||||
RSK_STARTING_SKULLTULA_TOKEN,
|
||||
RSK_STARTING_HEARTS,
|
||||
RSK_DAMAGE_MULTIPLIER,
|
||||
RSK_ALL_LOCATIONS_REACHABLE,
|
||||
RSK_SHUFFLE_BOSS_ENTRANCES,
|
||||
RSK_SHUFFLE_100_GS_REWARD,
|
||||
@@ -3563,6 +3622,15 @@ typedef enum {
|
||||
RO_GANON_BOSS_KEY_TRIFORCE_HUNT,
|
||||
} RandoOptionGanonsBossKey;
|
||||
|
||||
typedef enum {
|
||||
RO_LACS_VANILLA,
|
||||
RO_LACS_STONES,
|
||||
RO_LACS_MEDALLIONS,
|
||||
RO_LACS_REWARDS,
|
||||
RO_LACS_DUNGEONS,
|
||||
RO_LACS_TOKENS,
|
||||
} RandoOptionLACSCondition;
|
||||
|
||||
// LACS Reward Options settings (Standard rewards, Greg as reward, Greg as wildcard)
|
||||
typedef enum {
|
||||
RO_LACS_STANDARD_REWARD,
|
||||
@@ -3687,10 +3755,22 @@ typedef enum {
|
||||
// Logic (glitchless/no logic)
|
||||
typedef enum {
|
||||
RO_LOGIC_GLITCHLESS,
|
||||
//RO_LOGIC_GLITCHED,
|
||||
RO_LOGIC_GLITCHED,
|
||||
RO_LOGIC_NO_LOGIC,
|
||||
RO_LOGIC_VANILLA
|
||||
} RandoOptionLogic;
|
||||
|
||||
// Damage Multiplier
|
||||
typedef enum {
|
||||
RO_DAMAGE_MULTIPLIER_HALF,
|
||||
RO_DAMAGE_MULTIPLIER_DEFAULT,
|
||||
RO_DAMAGE_MULTIPLIER_DOUBLE,
|
||||
RO_DAMAGE_MULTIPLIER_QUADRUPLE,
|
||||
RO_DAMAGE_MULTIPLIER_OCTUPLE,
|
||||
RO_DAMAGE_MULTIPLIER_SEXDECUPLE,
|
||||
RO_DAMAGE_MULTIPLIER_OHKO,
|
||||
} RandoOptionDamageMultiplier;
|
||||
|
||||
// MQ Dungeons
|
||||
typedef enum {
|
||||
RO_MQ_DUNGEONS_NONE,
|
||||
@@ -3699,6 +3779,23 @@ typedef enum {
|
||||
RO_MQ_DUNGEONS_SELECTION,
|
||||
} RandoOptionMQDungeons;
|
||||
|
||||
typedef enum {
|
||||
RO_LOCATION_INCLUDE,
|
||||
RO_LOCATION_EXCLUDE,
|
||||
} RandoOptionLocationInclusion;
|
||||
|
||||
typedef enum {
|
||||
RO_CHEST_GAME_OFF,
|
||||
RO_CHEST_GAME_SINGLE_KEYS,
|
||||
RO_CHEST_GAME_PACK,
|
||||
} RandoOptionChestGame;
|
||||
|
||||
typedef enum {
|
||||
RO_MQ_SET_VANILLA,
|
||||
RO_MQ_SET_MQ,
|
||||
RO_MQ_SET_RANDOM,
|
||||
} RandoOptionMQSet;
|
||||
|
||||
typedef enum {
|
||||
CAN_OBTAIN,
|
||||
CANT_OBTAIN_MISC,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "randomizer_entrance_tracker.h"
|
||||
#include "randomizer_item_tracker.h"
|
||||
#include "randomizerTypes.h"
|
||||
#include "dungeon.h"
|
||||
#include "../../OTRGlobals.h"
|
||||
#include "../../UIWidgets.hpp"
|
||||
|
||||
@@ -732,8 +733,8 @@ void LoadFile() {
|
||||
areaChecksGotten[startingArea]++;
|
||||
}
|
||||
|
||||
showVOrMQ = (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_RANDOM_NUMBER ||
|
||||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SET_NUMBER &&
|
||||
showVOrMQ = (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_RANDOM_NUMBER ||
|
||||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SET_NUMBER &&
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) < 12));
|
||||
LinksPocket();
|
||||
SongFromImpa();
|
||||
@@ -926,7 +927,7 @@ void CheckTrackerWindow::DrawElement() {
|
||||
|
||||
if (isThisAreaSpoiled) {
|
||||
if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) {
|
||||
if (OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(DungeonSceneLookupByArea(rcArea)))
|
||||
if (OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(DungeonSceneLookupByArea(rcArea))->IsMQ())
|
||||
ImGui::Text("(%d/%d) - MQ", areaChecksGotten[rcArea], areaChecksTotal);
|
||||
else
|
||||
ImGui::Text("(%d/%d) - Vanilla", areaChecksGotten[rcArea], areaChecksTotal);
|
||||
@@ -1033,7 +1034,7 @@ void LoadSettings() {
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_FROG_SONG_RUPEES) == RO_GENERIC_YES
|
||||
: false;
|
||||
showStartingMapsCompasses = IS_RANDO ?
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_MAPS_COMPASSES) != RO_DUNGEON_ITEM_LOC_VANILLA
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_MAPANDCOMPASS) != RO_DUNGEON_ITEM_LOC_VANILLA
|
||||
: false;
|
||||
showKeysanity = IS_RANDO ?
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_KEYSANITY) != RO_DUNGEON_ITEM_LOC_VANILLA
|
||||
@@ -1111,8 +1112,8 @@ bool IsVisibleInCheckTracker(RandomizerCheck rc) {
|
||||
(rc != RC_LINKS_POCKET || showLinksPocket) &&
|
||||
(!RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()) ||
|
||||
loc->GetQuest() == RCQUEST_BOTH ||
|
||||
loc->GetQuest() == RCQUEST_MQ && OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(loc->GetScene()) ||
|
||||
loc->GetQuest() == RCQUEST_VANILLA && !OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(loc->GetScene())
|
||||
loc->GetQuest() == RCQUEST_MQ && OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc->GetScene())->IsMQ() ||
|
||||
loc->GetQuest() == RCQUEST_VANILLA && OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc->GetScene())->IsVanilla()
|
||||
) &&
|
||||
(loc->GetRCType() != RCTYPE_SHOP || (showShops && (!hideShopRightChecks || hideShopRightChecks && loc->GetActorParams() > 0x03))) &&
|
||||
(loc->GetRandomizerCheck() != RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS) &&
|
||||
@@ -1154,8 +1155,8 @@ bool IsVisibleInCheckTracker(RandomizerCheck rc) {
|
||||
}
|
||||
else if (loc->IsVanillaCompletion()) {
|
||||
return (loc->GetQuest() == RCQUEST_BOTH ||
|
||||
loc->GetQuest() == RCQUEST_MQ && OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(loc->GetScene()) ||
|
||||
loc->GetQuest() == RCQUEST_VANILLA && !OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(loc->GetScene()) ||
|
||||
loc->GetQuest() == RCQUEST_MQ && OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc->GetScene())->IsMQ() ||
|
||||
loc->GetQuest() == RCQUEST_VANILLA && OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc->GetScene())->IsVanilla() ||
|
||||
rc == RC_GIFT_FROM_SAGES) && rc != RC_LINKS_POCKET;
|
||||
}
|
||||
return false;
|
||||
@@ -1242,6 +1243,7 @@ void DrawLocation(RandomizerCheck rc) {
|
||||
std::string txt;
|
||||
bool showHidden = CVarGetInteger("gCheckTrackerOptionShowHidden", 0);
|
||||
Rando::Location* loc = Rando::StaticData::GetLocation(rc);
|
||||
Rando::ItemLocation* itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc);
|
||||
RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rc];
|
||||
RandomizerCheckStatus status = checkData.status;
|
||||
bool skipped = checkData.skipped;
|
||||
@@ -1335,7 +1337,7 @@ void DrawLocation(RandomizerCheck rc) {
|
||||
case RCSHOW_COLLECTED:
|
||||
case RCSHOW_SCUMMED:
|
||||
if (IS_RANDO) {
|
||||
txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rc].get.rgID][gSaveContext.language];
|
||||
txt = itemLoc->GetPlacedItem().GetName().GetForLanguage(gSaveContext.language);
|
||||
} else {
|
||||
if (IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID())) {
|
||||
if (gSaveContext.language == LANGUAGE_ENG || gSaveContext.language == LANGUAGE_GER) {
|
||||
@@ -1349,14 +1351,14 @@ void DrawLocation(RandomizerCheck rc) {
|
||||
case RCSHOW_IDENTIFIED:
|
||||
case RCSHOW_SEEN:
|
||||
if (IS_RANDO) {
|
||||
if (gSaveContext.itemLocations[rc].get.rgID == RG_ICE_TRAP) {
|
||||
if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP) {
|
||||
if (status == RCSHOW_IDENTIFIED) {
|
||||
txt = gSaveContext.itemLocations[rc].get.trickName;
|
||||
txt = OTRGlobals::Instance->gRandoContext->overrides[rc].GetTrickName().GetForLanguage(gSaveContext.language);
|
||||
} else {
|
||||
txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rc].get.fakeRgID][gSaveContext.language];
|
||||
txt = Rando::StaticData::RetrieveItem(OTRGlobals::Instance->gRandoContext->overrides[rc].LooksLike()).GetName().GetForLanguage(gSaveContext.language);
|
||||
}
|
||||
} else {
|
||||
txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rc].get.rgID][gSaveContext.language];
|
||||
txt = itemLoc->GetPlacedItem().GetName().GetForLanguage(gSaveContext.language);
|
||||
}
|
||||
if (status == RCSHOW_IDENTIFIED) {
|
||||
txt += fmt::format(" - {}", gSaveContext.checkTrackerData[rc].price);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "global.h"
|
||||
#include "entrance.h"
|
||||
|
||||
extern PlayState* gPlayState;
|
||||
|
||||
@@ -114,6 +115,7 @@ void Entrance_ResetEntranceTable(void) {
|
||||
}
|
||||
|
||||
void Entrance_Init(void) {
|
||||
EntranceOverride* entranceOverrides = Randomizer_GetEntranceOverrides();
|
||||
s32 index;
|
||||
|
||||
size_t blueWarpRemapIdx = 0;
|
||||
@@ -153,13 +155,13 @@ void Entrance_Init(void) {
|
||||
// Then overwrite the indices which are shuffled
|
||||
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
|
||||
|
||||
if (Entrance_EntranceIsNull(&gSaveContext.entranceOverrides[i])) {
|
||||
if (Entrance_EntranceIsNull(&entranceOverrides[i])) {
|
||||
break;
|
||||
}
|
||||
|
||||
s16 originalIndex = gSaveContext.entranceOverrides[i].index;
|
||||
s16 blueWarpIndex = gSaveContext.entranceOverrides[i].blueWarp;
|
||||
s16 overrideIndex = gSaveContext.entranceOverrides[i].override;
|
||||
s16 originalIndex = entranceOverrides[i].index;
|
||||
s16 blueWarpIndex = entranceOverrides[i].blueWarp;
|
||||
s16 overrideIndex = entranceOverrides[i].override;
|
||||
|
||||
//Overwrite grotto related indices
|
||||
if (originalIndex >= ENTRANCE_RANDO_GROTTO_EXIT_START) {
|
||||
@@ -785,6 +787,7 @@ u8 Entrance_GetIsEntranceDiscovered(u16 entranceIndex) {
|
||||
}
|
||||
|
||||
void Entrance_SetEntranceDiscovered(u16 entranceIndex) {
|
||||
EntranceOverride* entranceOverrides = Randomizer_GetEntranceOverrides();
|
||||
// Skip if already set to save time from setting the connected entrance or
|
||||
// if this entrance is outside of the randomized entrance range (i.e. is a dynamic entrance)
|
||||
if (entranceIndex > MAX_ENTRANCE_RANDO_USED_INDEX || Entrance_GetIsEntranceDiscovered(entranceIndex)) {
|
||||
@@ -798,8 +801,8 @@ void Entrance_SetEntranceDiscovered(u16 entranceIndex) {
|
||||
gSaveContext.sohStats.entrancesDiscovered[idx] |= entranceBit;
|
||||
// Set connected
|
||||
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
|
||||
if (entranceIndex == gSaveContext.entranceOverrides[i].index) {
|
||||
Entrance_SetEntranceDiscovered(gSaveContext.entranceOverrides[i].overrideDestination);
|
||||
if (entranceIndex == entranceOverrides[i].index) {
|
||||
Entrance_SetEntranceDiscovered(entranceOverrides[i].overrideDestination);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "entrance.h"
|
||||
|
||||
#define COLOR_ORANGE IM_COL32(230, 159, 0, 255)
|
||||
#define COLOR_GREEN IM_COL32(0, 158, 115, 255)
|
||||
@@ -459,6 +460,7 @@ void SortEntranceListByType(EntranceOverride* entranceList, u8 byDest) {
|
||||
}
|
||||
|
||||
void SortEntranceListByArea(EntranceOverride* entranceList, u8 byDest) {
|
||||
auto entranceCtx = Rando::Context::GetInstance()->GetEntranceShuffler();
|
||||
EntranceOverride tempList[ENTRANCE_OVERRIDES_MAX_COUNT] = { 0 };
|
||||
|
||||
// Store to temp
|
||||
@@ -498,10 +500,10 @@ void SortEntranceListByArea(EntranceOverride* entranceList, u8 byDest) {
|
||||
// and otherwise by group
|
||||
for (size_t group = ENTRANCE_GROUP_KOKIRI_FOREST; group < SPOILER_ENTRANCE_GROUP_COUNT; group++) {
|
||||
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
|
||||
if (Entrance_EntranceIsNull(&gSaveContext.entranceOverrides[i])) {
|
||||
if (Entrance_EntranceIsNull(&entranceCtx->entranceOverrides[i])) {
|
||||
continue;
|
||||
}
|
||||
const EntranceData* curEntrance = GetEntranceData(gSaveContext.entranceOverrides[i].index);
|
||||
const EntranceData* curEntrance = GetEntranceData(entranceCtx->entranceOverrides[i].index);
|
||||
if (curEntrance->srcGroup != group) {
|
||||
continue;
|
||||
}
|
||||
@@ -561,6 +563,7 @@ void ClearEntranceTrackingData() {
|
||||
}
|
||||
|
||||
void InitEntranceTrackingData() {
|
||||
auto entranceCtx = Rando::Context::GetInstance()->GetEntranceShuffler();
|
||||
gEntranceTrackingData = {0};
|
||||
|
||||
// Check if entrance randomization is disabled
|
||||
@@ -570,11 +573,11 @@ void InitEntranceTrackingData() {
|
||||
|
||||
// Set total and group counts
|
||||
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
|
||||
if (Entrance_EntranceIsNull(&gSaveContext.entranceOverrides[i])) {
|
||||
if (Entrance_EntranceIsNull(&entranceCtx->entranceOverrides[i])) {
|
||||
break;
|
||||
}
|
||||
const EntranceData* index = GetEntranceData(gSaveContext.entranceOverrides[i].index);
|
||||
const EntranceData* override = GetEntranceData(gSaveContext.entranceOverrides[i].override);
|
||||
const EntranceData* index = GetEntranceData(entranceCtx->entranceOverrides[i].index);
|
||||
const EntranceData* override = GetEntranceData(entranceCtx->entranceOverrides[i].override);
|
||||
|
||||
if (index->srcGroup == ENTRANCE_GROUP_ONE_WAY) {
|
||||
gEntranceTrackingData.GroupEntranceCounts[ENTRANCE_SOURCE_AREA][ENTRANCE_GROUP_ONE_WAY]++;
|
||||
@@ -616,10 +619,10 @@ void InitEntranceTrackingData() {
|
||||
|
||||
// Sort entrances by group and type in entranceData
|
||||
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
|
||||
srcListSortedByArea[i] = gSaveContext.entranceOverrides[i];
|
||||
destListSortedByArea[i] = gSaveContext.entranceOverrides[i];
|
||||
srcListSortedByType[i] = gSaveContext.entranceOverrides[i];
|
||||
destListSortedByType[i] = gSaveContext.entranceOverrides[i];
|
||||
srcListSortedByArea[i] = entranceCtx->entranceOverrides[i];
|
||||
destListSortedByArea[i] = entranceCtx->entranceOverrides[i];
|
||||
srcListSortedByType[i] = entranceCtx->entranceOverrides[i];
|
||||
destListSortedByType[i] = entranceCtx->entranceOverrides[i];
|
||||
}
|
||||
SortEntranceListByArea(srcListSortedByArea, 0);
|
||||
SortEntranceListByArea(destListSortedByArea, 1);
|
||||
|
||||
@@ -150,7 +150,7 @@ void SetStartingItems() {
|
||||
GiveLinkRupees(9001);
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAPANDCOMPASS) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
uint32_t mapBitMask = 1 << 1;
|
||||
uint32_t compassBitMask = 1 << 2;
|
||||
uint32_t startingDungeonItemsBitMask = mapBitMask | compassBitMask;
|
||||
|
||||
1798
soh/soh/Enhancements/randomizer/settings.cpp
Normal file
1798
soh/soh/Enhancements/randomizer/settings.cpp
Normal file
File diff suppressed because it is too large
Load Diff
49
soh/soh/Enhancements/randomizer/settings.h
Normal file
49
soh/soh/Enhancements/randomizer/settings.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "option.h"
|
||||
#include "randomizerTypes.h"
|
||||
#include "3drando/spoiler_log.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace Rando {
|
||||
class Settings {
|
||||
public:
|
||||
Settings();
|
||||
void CreateOptions();
|
||||
Option& Setting(RandomizerSettingKey key);
|
||||
Option& GetTrickOption(RandomizerTrick key);
|
||||
const std::array<Option, RSK_MAX>& GetAllOptions() const;
|
||||
std::vector<Option*>& GetExcludeOptionsForGroup(SpoilerCollectionCheckGroup group);
|
||||
const std::vector<std::vector<Option*>>& GetExcludeLocationsOptions() const;
|
||||
RandoOptionStartingAge ResolvedStartingAge() const;
|
||||
RandoOptionLACSCondition LACSCondition() const;
|
||||
std::string GetHash() const;
|
||||
const std::string& GetSeedString() const;
|
||||
void SetSeedString(std::string seedString);
|
||||
const uint32_t GetSeed() const;
|
||||
void SetSeed(uint32_t seed);
|
||||
void SetHash(std::string hash);
|
||||
const std::array<OptionGroup, RSG_MAX>& GetOptionGroups();
|
||||
const OptionGroup& GetOptionGroup(RandomizerSettingGroupKey key);
|
||||
void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings,
|
||||
std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks);
|
||||
void ParseJson(nlohmann::json spoilerFileJson);
|
||||
std::vector<Option*> VanillaLogicDefaults = {};
|
||||
|
||||
private:
|
||||
std::array<Option, RSK_MAX> mOptions = {};
|
||||
std::array<OptionGroup, RSG_MAX> mOptionGroups = {};
|
||||
std::array<Option, RT_MAX> mTrickOptions;
|
||||
std::vector<std::vector<Option*>> mExcludeLocationsOptionsGroups;
|
||||
std::unordered_map<std::string, RandomizerSettingKey> mSpoilerfileSettingNameToEnum;
|
||||
RandoOptionStartingAge mResolvedStartingAge;
|
||||
RandoOptionLACSCondition mLACSCondition;
|
||||
std::string mHash;
|
||||
std::string mSeedString;
|
||||
uint32_t mFinalSeed;
|
||||
};
|
||||
} // namespace Rando
|
||||
82
soh/soh/Enhancements/randomizer/trial.cpp
Normal file
82
soh/soh/Enhancements/randomizer/trial.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "trial.h"
|
||||
|
||||
namespace Rando {
|
||||
TrialInfo::TrialInfo(const Text name_) : name(std::move(name_)) {}
|
||||
TrialInfo::TrialInfo() = default;
|
||||
TrialInfo::~TrialInfo() = default;
|
||||
|
||||
Text TrialInfo::GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
bool TrialInfo::IsSkipped() const {
|
||||
return skipped;
|
||||
}
|
||||
|
||||
bool TrialInfo::IsRequired() const {
|
||||
return !skipped;
|
||||
}
|
||||
|
||||
void TrialInfo::SetAsRequired() {
|
||||
skipped = false;
|
||||
}
|
||||
|
||||
void TrialInfo::SetAsSkipped() {
|
||||
skipped = true;
|
||||
}
|
||||
|
||||
Trials::Trials() {
|
||||
mTrials[FOREST_TRIAL] = TrialInfo(Text{"the Forest Trial", "l'épreuve de la Forêt", "la prueba del bosque"});
|
||||
mTrials[FIRE_TRIAL] = TrialInfo(Text{"the Fire Trial", "l'épreuve du Feu", "la prueba del fuego"});
|
||||
mTrials[WATER_TRIAL] = TrialInfo(Text{"the Water Trial", "l'épreuve de l'Eau", "la prueba del agua"});
|
||||
mTrials[SPIRIT_TRIAL] = TrialInfo(Text{"the Spirit Trial", "l'épreuve de l'Esprit", "la prueba del espíritu"});
|
||||
mTrials[SHADOW_TRIAL] = TrialInfo(Text{"the Shadow Trial", "l'épreuve de l'Ombre", "la prueba de las sombras"});
|
||||
mTrials[LIGHT_TRIAL] = TrialInfo(Text{"the Light Trial", "l'épreuve de la Lumière", "la prueba de la luz"});
|
||||
}
|
||||
Trials::~Trials() = default;
|
||||
|
||||
TrialInfo* Trials::GetTrial(TrialKey key) {
|
||||
return &mTrials[key];
|
||||
}
|
||||
|
||||
void Trials::SkipAll() {
|
||||
for (TrialInfo& trial : mTrials) {
|
||||
trial.SetAsSkipped();
|
||||
}
|
||||
}
|
||||
|
||||
void Trials::RequireAll() {
|
||||
for (TrialInfo& trial : mTrials) {
|
||||
trial.SetAsRequired();
|
||||
}
|
||||
}
|
||||
|
||||
std::array<TrialInfo*, 6> Trials::GetTrialList() {
|
||||
std::array<TrialInfo*, 6> trialList;
|
||||
for (size_t i = 0; i < mTrials.size(); i++) {
|
||||
trialList[i] = &mTrials[i];
|
||||
}
|
||||
return trialList;
|
||||
}
|
||||
|
||||
size_t Trials::GetTrialListSize() {
|
||||
return mTrials.size();
|
||||
}
|
||||
void Trials::ParseJson(nlohmann::json spoilerFileJson) {
|
||||
try {
|
||||
nlohmann::json trialsJson = spoilerFileJson["requiredTrials"];
|
||||
for (auto it = trialsJson.begin(); it != trialsJson.end(); it++) {
|
||||
std::string trialName = it.value().template get<std::string>();
|
||||
for (auto& trial : mTrials) {
|
||||
if (trial.GetName() == trialName) {
|
||||
trial.SetAsRequired();
|
||||
} else {
|
||||
trial.SetAsSkipped();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} // namespace Rando
|
||||
47
soh/soh/Enhancements/randomizer/trial.h
Normal file
47
soh/soh/Enhancements/randomizer/trial.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "3drando/text.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace Rando {
|
||||
class TrialInfo {
|
||||
public:
|
||||
TrialInfo(const Text name_);
|
||||
TrialInfo();
|
||||
~TrialInfo();
|
||||
|
||||
Text GetName() const;
|
||||
bool IsSkipped() const;
|
||||
bool IsRequired() const;
|
||||
void SetAsRequired();
|
||||
void SetAsSkipped();
|
||||
private:
|
||||
Text name;
|
||||
bool skipped = true;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
LIGHT_TRIAL,
|
||||
FOREST_TRIAL,
|
||||
FIRE_TRIAL,
|
||||
WATER_TRIAL,
|
||||
SPIRIT_TRIAL,
|
||||
SHADOW_TRIAL,
|
||||
} TrialKey;
|
||||
|
||||
class Trials {
|
||||
public:
|
||||
Trials();
|
||||
~Trials();
|
||||
TrialInfo* GetTrial(TrialKey key);
|
||||
void SkipAll();
|
||||
void RequireAll();
|
||||
std::array<TrialInfo*, 6> GetTrialList();
|
||||
size_t GetTrialListSize();
|
||||
void ParseJson(nlohmann::json spoilerFileJson);
|
||||
private:
|
||||
std::array<TrialInfo, 6> mTrials;
|
||||
};
|
||||
}
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "Enhancements/randomizer/randomizer_check_tracker.h"
|
||||
#include "Enhancements/randomizer/3drando/random.hpp"
|
||||
#include "Enhancements/randomizer/static_data.h"
|
||||
#include "Enhancements/randomizer/dungeon.h"
|
||||
#include "Enhancements/gameplaystats.h"
|
||||
#include "Enhancements/n64_weird_frame_data.inc"
|
||||
#include "frame_interpolation.h"
|
||||
@@ -295,6 +296,8 @@ OTRGlobals::OTRGlobals() {
|
||||
|
||||
gSaveStateMgr = std::make_shared<SaveStateMgr>();
|
||||
gRandoContext = Rando::Context::CreateInstance();
|
||||
gRandoContext->AddExcludedOptions();
|
||||
gRandoContext->GetSettings()->CreateOptions();
|
||||
gRandomizer = std::make_shared<Randomizer>();
|
||||
|
||||
hasMasterQuest = hasOriginal = false;
|
||||
@@ -1144,10 +1147,11 @@ uint32_t IsSceneMasterQuest(s16 sceneNum) {
|
||||
value = 1;
|
||||
} else {
|
||||
value = 0;
|
||||
if (IS_RANDO &&
|
||||
!OTRGlobals::Instance->gRandomizer->masterQuestDungeons.empty() &&
|
||||
OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(sceneNum)) {
|
||||
value = 1;
|
||||
if (IS_RANDO) {
|
||||
auto dungeon = OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(sceneNum);
|
||||
if (dungeon != nullptr && dungeon->IsMQ()) {
|
||||
value = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1316,7 +1320,12 @@ extern "C" char* ResourceMgr_LoadIfDListByName(const char* filePath) {
|
||||
}
|
||||
|
||||
extern "C" Sprite* GetSeedTexture(uint8_t index) {
|
||||
return OTRGlobals::Instance->gRandomizer->GetSeedTexture(index);
|
||||
|
||||
return OTRGlobals::Instance->gRandoContext->GetSeedTexture(index);
|
||||
}
|
||||
|
||||
extern "C" uint8_t GetSeedIconIndex(uint8_t index) {
|
||||
return OTRGlobals::Instance->gRandoContext->hashIconIndexes[index];
|
||||
}
|
||||
|
||||
extern "C" char* ResourceMgr_LoadPlayerAnimByName(const char* animPath) {
|
||||
@@ -1938,44 +1947,28 @@ extern "C" int GetEquipNowMessage(char* buffer, char* src, const int maxBufferSi
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_LoadSettings(const char* spoilerFileName) {
|
||||
OTRGlobals::Instance->gRandomizer->LoadRandomizerSettings(spoilerFileName);
|
||||
extern "C" void Randomizer_ParseSpoiler(const char* fileLoc) {
|
||||
OTRGlobals::Instance->gRandoContext->ParseSpoiler(fileLoc, CVarGetInteger("gPlandoMode", 0));
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_LoadHintLocations(const char* spoilerFileName) {
|
||||
OTRGlobals::Instance->gRandomizer->LoadHintLocations(spoilerFileName);
|
||||
extern "C" void Randomizer_LoadHintMessages() {
|
||||
OTRGlobals::Instance->gRandomizer->LoadHintMessages();
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_LoadMerchantMessages(const char* spoilerFileName) {
|
||||
OTRGlobals::Instance->gRandomizer->LoadMerchantMessages(spoilerFileName);
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_LoadRequiredTrials(const char* spoilerFileName) {
|
||||
OTRGlobals::Instance->gRandomizer->LoadRequiredTrials(spoilerFileName);
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_LoadMasterQuestDungeons(const char* spoilerFileName) {
|
||||
OTRGlobals::Instance->gRandomizer->LoadMasterQuestDungeons(spoilerFileName);
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent) {
|
||||
OTRGlobals::Instance->gRandomizer->LoadItemLocations(spoilerFileName, silent);
|
||||
extern "C" void Randomizer_LoadMerchantMessages() {
|
||||
OTRGlobals::Instance->gRandomizer->LoadMerchantMessages();
|
||||
}
|
||||
|
||||
extern "C" bool Randomizer_IsTrialRequired(RandomizerInf trial) {
|
||||
return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trial);
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_LoadEntranceOverrides(const char* spoilerFileName, bool silent) {
|
||||
OTRGlobals::Instance->gRandomizer->LoadEntranceOverrides(spoilerFileName, silent);
|
||||
}
|
||||
|
||||
extern "C" u32 SpoilerFileExists(const char* spoilerFileName) {
|
||||
return OTRGlobals::Instance->gRandomizer->SpoilerFileExists(spoilerFileName);
|
||||
}
|
||||
|
||||
extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey) {
|
||||
return OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(randoSettingKey);
|
||||
return OTRGlobals::Instance->gRandoContext->GetOption(randoSettingKey).GetSelectedOptionIndex();
|
||||
}
|
||||
|
||||
extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams) {
|
||||
@@ -2023,6 +2016,38 @@ extern "C" ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck(
|
||||
return OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck);
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_GenerateSeed() {
|
||||
std::string seed = "";
|
||||
if (OTRGlobals::Instance->gRandoContext->IsSpoilerLoaded()) {
|
||||
seed = OTRGlobals::Instance->gRandoContext->GetSettings()->GetSeedString();
|
||||
}
|
||||
GenerateRandomizer(seed);
|
||||
}
|
||||
|
||||
extern "C" uint8_t Randomizer_IsSeedGenerated() {
|
||||
return OTRGlobals::Instance->gRandoContext->IsSeedGenerated() ? 1 : 0;
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_SetSeedGenerated(bool seedGenerated) {
|
||||
OTRGlobals::Instance->gRandoContext->SetSeedGenerated(seedGenerated);
|
||||
}
|
||||
|
||||
extern "C" uint8_t Randomizer_IsSpoilerLoaded() {
|
||||
return OTRGlobals::Instance->gRandoContext->IsSpoilerLoaded() ? 1 : 0;
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_SetSpoilerLoaded(bool spoilerLoaded) {
|
||||
OTRGlobals::Instance->gRandoContext->SetSpoilerLoaded(spoilerLoaded);
|
||||
}
|
||||
|
||||
extern "C" uint8_t Randomizer_IsPlandoLoaded() {
|
||||
return OTRGlobals::Instance->gRandoContext->IsPlandoLoaded() ? 1 : 0;
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_SetPlandoLoaded(bool plandoLoaded) {
|
||||
OTRGlobals::Instance->gRandoContext->SetPlandoLoaded(plandoLoaded);
|
||||
}
|
||||
|
||||
CustomMessage Randomizer_GetCustomGetItemMessage(Player* player) {
|
||||
s16 giid;
|
||||
if (player->getItemEntry.objectId != OBJECT_INVALID) {
|
||||
@@ -2057,7 +2082,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
||||
messageEntry = Randomizer_GetCustomGetItemMessage(player);
|
||||
}
|
||||
} else if (textId == TEXT_ITEM_DUNGEON_MAP || textId == TEXT_ITEM_COMPASS) {
|
||||
if (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_STARTING_MAPS_COMPASSES)) {
|
||||
if (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS)) {
|
||||
if (textId == TEXT_ITEM_DUNGEON_MAP) {
|
||||
messageEntry = OTRGlobals::Instance->gRandomizer->GetMapGetItemMessageWithHint(player->getItemEntry);
|
||||
} else {
|
||||
|
||||
@@ -127,24 +127,28 @@ void* getN64WeirdFrame(s32 i);
|
||||
int GetEquipNowMessage(char* buffer, char* src, const int maxBufferSize);
|
||||
u32 SpoilerFileExists(const char* spoilerFileName);
|
||||
Sprite* GetSeedTexture(uint8_t index);
|
||||
void Randomizer_LoadSettings(const char* spoilerFileName);
|
||||
uint8_t GetSeedIconIndex(uint8_t index);
|
||||
u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
|
||||
RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams);
|
||||
ScrubIdentity Randomizer_IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
|
||||
ShopItemIdentity Randomizer_IdentifyShopItem(s32 sceneNum, u8 slotIndex);
|
||||
CowIdentity Randomizer_IdentifyCow(s32 sceneNum, s32 posX, s32 posZ);
|
||||
void Randomizer_LoadHintLocations(const char* spoilerFileName);
|
||||
void Randomizer_LoadMerchantMessages(const char* spoilerFileName);
|
||||
void Randomizer_LoadRequiredTrials(const char* spoilerFileName);
|
||||
void Randomizer_LoadMasterQuestDungeons(const char* spoilerFileName);
|
||||
void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent);
|
||||
void Randomizer_LoadEntranceOverrides(const char* spoilerFileName, bool silent);
|
||||
void Randomizer_ParseSpoiler(const char* fileLoc);
|
||||
void Randomizer_LoadHintMessages();
|
||||
void Randomizer_LoadMerchantMessages();
|
||||
bool Randomizer_IsTrialRequired(RandomizerInf trial);
|
||||
GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId);
|
||||
GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId);
|
||||
GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||
GetItemEntry Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||
ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck);
|
||||
void Randomizer_GenerateSeed();
|
||||
uint8_t Randomizer_IsSeedGenerated();
|
||||
void Randomizer_SetSeedGenerated(bool seedGenerated);
|
||||
uint8_t Randomizer_IsSpoilerLoaded();
|
||||
void Randomizer_SetSpoilerLoaded(bool spoilerLoaded);
|
||||
uint8_t Randomizer_IsPlandoLoaded();
|
||||
void Randomizer_SetPlandoLoaded(bool plandoLoaded);
|
||||
int CustomMessage_RetrieveIfExists(PlayState* play);
|
||||
void Overlay_DisplayText(float duration, const char* text);
|
||||
void Overlay_DisplayText_Seconds(int seconds, const char* text);
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#include "SaveManager.h"
|
||||
#include "OTRGlobals.h"
|
||||
#include "Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "Enhancements/randomizer/context.h"
|
||||
#include "Enhancements/randomizer/entrance.h"
|
||||
#include "Enhancements/randomizer/dungeon.h"
|
||||
#include "Enhancements/randomizer/trial.h"
|
||||
#include "soh/util.h"
|
||||
|
||||
#include "z64.h"
|
||||
@@ -61,7 +65,8 @@ SaveManager::SaveManager() {
|
||||
|
||||
AddLoadFunction("randomizer", 1, LoadRandomizerVersion1);
|
||||
AddLoadFunction("randomizer", 2, LoadRandomizerVersion2);
|
||||
AddSaveFunction("randomizer", 2, SaveRandomizer, true, SECTION_PARENT_NONE);
|
||||
AddLoadFunction("randomizer", 3, LoadRandomizerVersion3);
|
||||
AddSaveFunction("randomizer", 3, SaveRandomizer, true, SECTION_PARENT_NONE);
|
||||
|
||||
AddInitFunction(InitFileImpl);
|
||||
|
||||
@@ -92,47 +97,65 @@ SaveManager::SaveManager() {
|
||||
}
|
||||
|
||||
void SaveManager::LoadRandomizerVersion1() {
|
||||
for (int i = 0; i < ARRAY_COUNT(gSaveContext.itemLocations); i++) {
|
||||
auto randoContext = Rando::Context::GetInstance();
|
||||
RandomizerCheck location = RC_UNKNOWN_CHECK;
|
||||
for (int i = 0; i < RC_MAX; i++) {
|
||||
SaveManager::Instance->LoadData("check" + std::to_string(i), location);
|
||||
SaveManager::Instance->LoadStruct("get" + std::to_string(i), [&]() {
|
||||
SaveManager::Instance->LoadData("rgID", gSaveContext.itemLocations[i].get.rgID);
|
||||
SaveManager::Instance->LoadData("fakeRgID", gSaveContext.itemLocations[i].get.fakeRgID);
|
||||
SaveManager::Instance->LoadCharArray("trickName", gSaveContext.itemLocations[i].get.trickName,
|
||||
MAX_TRICK_NAME_SIZE);
|
||||
SaveManager::Instance->LoadData("rgID", randoContext->GetItemLocation(location)->RefPlacedItem());
|
||||
if (randoContext->GetItemLocation(location)->GetPlacedRandomizerGet() == RG_ICE_TRAP) {
|
||||
randoContext->overrides[location].SetLocation(location);
|
||||
SaveManager::Instance->LoadData("fakeRgID", randoContext->overrides[location].RefLooksLike());
|
||||
SaveManager::Instance->LoadData("trickName", randoContext->overrides[location].GetTrickName().english);
|
||||
SaveManager::Instance->LoadData("trickName", randoContext->overrides[location].GetTrickName().french);
|
||||
}
|
||||
});
|
||||
SaveManager::Instance->LoadData("check" + std::to_string(i), gSaveContext.itemLocations[i].check);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_COUNT(gSaveContext.seedIcons); i++) {
|
||||
SaveManager::Instance->LoadData("seed" + std::to_string(i), gSaveContext.seedIcons[i]);
|
||||
for (int i = 0; i < randoContext->hashIconIndexes.size(); i++) {
|
||||
SaveManager::Instance->LoadData("seed" + std::to_string(i), randoContext->hashIconIndexes[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_COUNT(gSaveContext.randoSettings); i++) {
|
||||
SaveManager::Instance->LoadData("sk" + std::to_string(i), gSaveContext.randoSettings[i].key);
|
||||
SaveManager::Instance->LoadData("sv" + std::to_string(i), gSaveContext.randoSettings[i].value);
|
||||
for (int i = 0; i < RSK_MAX; i++) {
|
||||
int key, value;
|
||||
SaveManager::Instance->LoadData("sk" + std::to_string(i), key);
|
||||
SaveManager::Instance->LoadData("sv" + std::to_string(i), value);
|
||||
randoContext->GetOption(RandomizerSettingKey(key)).SetSelectedIndex(value);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_COUNT(gSaveContext.hintLocations); i++) {
|
||||
SaveManager::Instance->LoadData("hc" + std::to_string(i), gSaveContext.hintLocations[i].check);
|
||||
for (int j = 0; j < ARRAY_COUNT(gSaveContext.hintLocations[i].hintText); j++) {
|
||||
SaveManager::Instance->LoadData("ht" + std::to_string(i) + "-" + std::to_string(j), gSaveContext.hintLocations[i].hintText[j]);
|
||||
for (int i = 0; i < 50; i++) {
|
||||
RandomizerCheck check;
|
||||
char hintText[200];
|
||||
SaveManager::Instance->LoadData("hc" + std::to_string(i), check);
|
||||
for (int j = 0; j < ARRAY_COUNT(hintText); j++) {
|
||||
SaveManager::Instance->LoadData("ht" + std::to_string(i) + "-" + std::to_string(j), hintText[j]);
|
||||
}
|
||||
randoContext->AddHint(RandomizerHintKey(check - RC_COLOSSUS_GOSSIP_STONE + 1), Text(hintText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_COUNT(gSaveContext.childAltarText); i++) {
|
||||
SaveManager::Instance->LoadData("cat" + std::to_string(i), gSaveContext.childAltarText[i]);
|
||||
char childAltarText[250];
|
||||
for (int i = 0; i < ARRAY_COUNT(childAltarText); i++) {
|
||||
SaveManager::Instance->LoadData("cat" + std::to_string(i), childAltarText[i]);
|
||||
}
|
||||
randoContext->AddHint(RH_ALTAR_CHILD, Text(childAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
|
||||
for (int i = 0; i < ARRAY_COUNT(gSaveContext.adultAltarText); i++) {
|
||||
SaveManager::Instance->LoadData("aat" + std::to_string(i), gSaveContext.adultAltarText[i]);
|
||||
char adultAltarText[750];
|
||||
for (int i = 0; i < ARRAY_COUNT(adultAltarText); i++) {
|
||||
SaveManager::Instance->LoadData("aat" + std::to_string(i), adultAltarText[i]);
|
||||
}
|
||||
randoContext->AddHint(RH_ALTAR_ADULT, Text(adultAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
|
||||
for (int i = 0; i < ARRAY_COUNT(gSaveContext.ganonHintText); i++) {
|
||||
SaveManager::Instance->LoadData("ght" + std::to_string(i), gSaveContext.ganonHintText[i]);
|
||||
char ganonHintText[150];
|
||||
for (int i = 0; i < ARRAY_COUNT(ganonHintText); i++) {
|
||||
SaveManager::Instance->LoadData("ght" + std::to_string(i), ganonHintText[i]);
|
||||
}
|
||||
randoContext->AddHint(RH_GANONDORF_HINT, Text(ganonHintText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
|
||||
for (int i = 0; i < ARRAY_COUNT(gSaveContext.ganonText); i++) {
|
||||
SaveManager::Instance->LoadData("gt" + std::to_string(i), gSaveContext.ganonText[i]);
|
||||
char ganonText[250];
|
||||
for (int i = 0; i < ARRAY_COUNT(ganonText); i++) {
|
||||
SaveManager::Instance->LoadData("gt" + std::to_string(i), ganonText[i]);
|
||||
}
|
||||
randoContext->AddHint(RH_GANONDORF_NOHINT, Text(ganonText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
|
||||
SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems);
|
||||
|
||||
@@ -140,14 +163,12 @@ void SaveManager::LoadRandomizerVersion1() {
|
||||
|
||||
SaveManager::Instance->LoadData("pendingIceTrapCount", gSaveContext.pendingIceTrapCount);
|
||||
|
||||
std::shared_ptr<Randomizer> randomizer = OTRGlobals::Instance->gRandomizer;
|
||||
|
||||
randomizer->LoadRandomizerSettings("");
|
||||
size_t merchantPricesSize = 0;
|
||||
if (randomizer->GetRandoSettingValue(RSK_SHUFFLE_SCRUBS) != RO_SCRUBS_OFF) {
|
||||
if (randoContext->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF)) {
|
||||
merchantPricesSize += NUM_SCRUBS;
|
||||
}
|
||||
if (randomizer->GetRandoSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_OFF) {
|
||||
if (randoContext->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF)) {
|
||||
merchantPricesSize += NUM_SHOP_ITEMS;
|
||||
}
|
||||
|
||||
@@ -157,84 +178,107 @@ void SaveManager::LoadRandomizerVersion1() {
|
||||
SaveManager::Instance->LoadData("check", rc);
|
||||
uint32_t price;
|
||||
SaveManager::Instance->LoadData("price", price);
|
||||
randomizer->merchantPrices[rc] = price;
|
||||
randoContext->GetItemLocation(rc)->SetCustomPrice(price);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void SaveManager::LoadRandomizerVersion2() {
|
||||
auto randoContext = Rando::Context::GetInstance();
|
||||
SaveManager::Instance->LoadArray("itemLocations", RC_MAX, [&](size_t i) {
|
||||
gSaveContext.itemLocations[i].check = RandomizerCheck(i);
|
||||
SaveManager::Instance->LoadStruct("", [&]() {
|
||||
SaveManager::Instance->LoadData("rgID", gSaveContext.itemLocations[i].get.rgID);
|
||||
SaveManager::Instance->LoadData("fakeRgID", gSaveContext.itemLocations[i].get.fakeRgID);
|
||||
SaveManager::Instance->LoadCharArray("trickName", gSaveContext.itemLocations[i].get.trickName,
|
||||
MAX_TRICK_NAME_SIZE);
|
||||
SaveManager::Instance->LoadData("rgID", randoContext->GetItemLocation(i)->RefPlacedItem());
|
||||
RandomizerGet rg = RG_NONE;
|
||||
SaveManager::Instance->LoadData("fakeRgID", rg, RG_NONE);
|
||||
if (rg != RG_NONE) {
|
||||
randoContext->overrides[static_cast<RandomizerCheck>(i)] = Rando::ItemOverride(static_cast<RandomizerCheck>(i), rg);
|
||||
SaveManager::Instance->LoadData("trickName", randoContext->overrides[static_cast<RandomizerCheck>(i)].GetTrickName().english);
|
||||
SaveManager::Instance->LoadData("trickName", randoContext->overrides[static_cast<RandomizerCheck>(i)].GetTrickName().french);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->LoadArray("entrances", ARRAY_COUNT(gSaveContext.entranceOverrides), [&](size_t i) {
|
||||
auto entranceCtx = randoContext->GetEntranceShuffler();
|
||||
SaveManager::Instance->LoadArray("entrances", ARRAY_COUNT(entranceCtx->entranceOverrides), [&](size_t i) {
|
||||
SaveManager::Instance->LoadStruct("", [&]() {
|
||||
SaveManager::Instance->LoadData("index", gSaveContext.entranceOverrides[i].index);
|
||||
SaveManager::Instance->LoadData("destination", gSaveContext.entranceOverrides[i].destination);
|
||||
SaveManager::Instance->LoadData("blueWarp", gSaveContext.entranceOverrides[i].blueWarp);
|
||||
SaveManager::Instance->LoadData("override", gSaveContext.entranceOverrides[i].override);
|
||||
SaveManager::Instance->LoadData("overrideDestination", gSaveContext.entranceOverrides[i].overrideDestination);
|
||||
SaveManager::Instance->LoadData("index", entranceCtx->entranceOverrides[i].index);
|
||||
SaveManager::Instance->LoadData("destination", entranceCtx->entranceOverrides[i].destination);
|
||||
SaveManager::Instance->LoadData("blueWarp", entranceCtx->entranceOverrides[i].blueWarp);
|
||||
SaveManager::Instance->LoadData("override", entranceCtx->entranceOverrides[i].override);
|
||||
SaveManager::Instance->LoadData("overrideDestination", entranceCtx->entranceOverrides[i].overrideDestination);
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->LoadArray("seed", ARRAY_COUNT(gSaveContext.seedIcons), [&](size_t i) {
|
||||
SaveManager::Instance->LoadData("", gSaveContext.seedIcons[i]);
|
||||
SaveManager::Instance->LoadArray("seed", randoContext->hashIconIndexes.size(), [&](size_t i) {
|
||||
SaveManager::Instance->LoadData("", randoContext->hashIconIndexes[i]);
|
||||
});
|
||||
|
||||
std::string inputSeed;
|
||||
SaveManager::Instance->LoadCharArray("inputSeed", gSaveContext.inputSeed, ARRAY_COUNT(gSaveContext.inputSeed));
|
||||
SaveManager::Instance->LoadData("inputSeed", inputSeed);
|
||||
randoContext->GetSettings()->SetSeedString(inputSeed);
|
||||
|
||||
SaveManager::Instance->LoadData("finalSeed", gSaveContext.finalSeed);
|
||||
uint32_t finalSeed;
|
||||
SaveManager::Instance->LoadData("finalSeed", finalSeed);
|
||||
randoContext->GetSettings()->SetSeed(finalSeed);
|
||||
|
||||
SaveManager::Instance->LoadArray("randoSettings", RSK_MAX, [&](size_t i) {
|
||||
gSaveContext.randoSettings[i].key = RandomizerSettingKey(i);
|
||||
SaveManager::Instance->LoadData("", gSaveContext.randoSettings[i].value);
|
||||
int value = 0;
|
||||
SaveManager::Instance->LoadData("", value);
|
||||
randoContext->GetOption(RandomizerSettingKey(i)).SetSelectedIndex(value);
|
||||
});
|
||||
|
||||
SaveManager::Instance->LoadArray("hintLocations", ARRAY_COUNT(gSaveContext.hintLocations), [&](size_t i) {
|
||||
SaveManager::Instance->LoadArray("hintLocations", RH_ZR_OPEN_GROTTO_GOSSIP_STONE + 1, [&](size_t i) {
|
||||
SaveManager::Instance->LoadStruct("", [&]() {
|
||||
SaveManager::Instance->LoadData("check", gSaveContext.hintLocations[i].check);
|
||||
SaveManager::Instance->LoadCharArray("hintText", gSaveContext.hintLocations[i].hintText,
|
||||
ARRAY_COUNT(gSaveContext.hintLocations[i].hintText));
|
||||
RandomizerCheck rc = RC_UNKNOWN_CHECK;
|
||||
SaveManager::Instance->LoadData("check", rc);
|
||||
std::string hintText;
|
||||
SaveManager::Instance->LoadData("hintText", hintText);
|
||||
randoContext->AddHint(RandomizerHintKey(rc - RC_COLOSSUS_GOSSIP_STONE + 1), Text(hintText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->LoadCharArray("childAltarText", gSaveContext.childAltarText,
|
||||
ARRAY_COUNT(gSaveContext.childAltarText));
|
||||
SaveManager::Instance->LoadCharArray("adultAltarText", gSaveContext.adultAltarText,
|
||||
ARRAY_COUNT(gSaveContext.adultAltarText));
|
||||
|
||||
SaveManager::Instance->LoadCharArray("ganonHintText", gSaveContext.ganonHintText,
|
||||
ARRAY_COUNT(gSaveContext.ganonHintText));
|
||||
SaveManager::Instance->LoadCharArray("ganonText", gSaveContext.ganonText, ARRAY_COUNT(gSaveContext.ganonText));
|
||||
|
||||
SaveManager::Instance->LoadCharArray("dampeText", gSaveContext.dampeText, ARRAY_COUNT(gSaveContext.dampeText));
|
||||
|
||||
SaveManager::Instance->LoadCharArray("gregHintText", gSaveContext.gregHintText,
|
||||
ARRAY_COUNT(gSaveContext.gregHintText));
|
||||
|
||||
SaveManager::Instance->LoadCharArray("sheikText", gSaveContext.sheikText, ARRAY_COUNT(gSaveContext.sheikText));
|
||||
|
||||
SaveManager::Instance->LoadCharArray("sariaText", gSaveContext.sariaText, ARRAY_COUNT(gSaveContext.sariaText));
|
||||
|
||||
SaveManager::Instance->LoadCharArray("warpMinuetText", gSaveContext.warpMinuetText,
|
||||
ARRAY_COUNT(gSaveContext.warpMinuetText));
|
||||
SaveManager::Instance->LoadCharArray("warpBoleroText", gSaveContext.warpBoleroText,
|
||||
ARRAY_COUNT(gSaveContext.warpBoleroText));
|
||||
SaveManager::Instance->LoadCharArray("warpSerenadeText", gSaveContext.warpSerenadeText,
|
||||
ARRAY_COUNT(gSaveContext.warpSerenadeText));
|
||||
SaveManager::Instance->LoadCharArray("warpRequiemText", gSaveContext.warpRequiemText,
|
||||
ARRAY_COUNT(gSaveContext.warpRequiemText));
|
||||
SaveManager::Instance->LoadCharArray("warpNocturneText", gSaveContext.warpNocturneText,
|
||||
ARRAY_COUNT(gSaveContext.warpNocturneText));
|
||||
SaveManager::Instance->LoadCharArray("warpPreludeText", gSaveContext.warpPreludeText,
|
||||
ARRAY_COUNT(gSaveContext.warpPreludeText));
|
||||
std::string childAltarText;
|
||||
SaveManager::Instance->LoadData("childAltarText", childAltarText);
|
||||
randoContext->AddHint(RH_ALTAR_CHILD, Text(childAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
std::string adultAltarText;
|
||||
SaveManager::Instance->LoadData("adultAltarText", adultAltarText);
|
||||
randoContext->AddHint(RH_ALTAR_ADULT, Text(adultAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
std::string ganonHintText;
|
||||
SaveManager::Instance->LoadData("ganonHintText", ganonHintText);
|
||||
randoContext->AddHint(RH_GANONDORF_HINT, Text(ganonHintText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
std::string ganonText;
|
||||
SaveManager::Instance->LoadData("ganonText", ganonText);
|
||||
randoContext->AddHint(RH_GANONDORF_NOHINT, Text(ganonText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
std::string dampeText;
|
||||
SaveManager::Instance->LoadData("dampeText", dampeText);
|
||||
randoContext->AddHint(RH_DAMPES_DIARY, Text(dampeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
std::string gregHintText;
|
||||
SaveManager::Instance->LoadData("gregHintText", gregHintText);
|
||||
randoContext->AddHint(RH_GREG_RUPEE, Text(gregHintText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
std::string sheikText;
|
||||
SaveManager::Instance->LoadData("sheikText", sheikText);
|
||||
randoContext->AddHint(RH_SHEIK_LIGHT_ARROWS, Text(sheikText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
std::string sariaText;
|
||||
SaveManager::Instance->LoadData("sariaText", sariaText);
|
||||
randoContext->AddHint(RH_SARIA, Text(sariaText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
|
||||
std::string warpMinuetText;
|
||||
SaveManager::Instance->LoadData("warpMinuetText", warpMinuetText);
|
||||
randoContext->AddHint(RH_MINUET_WARP_LOC, Text(warpMinuetText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpMinuetText));
|
||||
std::string warpBoleroText;
|
||||
SaveManager::Instance->LoadData("warpBoleroText", warpBoleroText);
|
||||
randoContext->AddHint(RH_BOLERO_WARP_LOC, Text(warpBoleroText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpBoleroText));
|
||||
std::string warpSerenadeText;
|
||||
SaveManager::Instance->LoadData("warpSerenadeText", warpSerenadeText);
|
||||
randoContext->AddHint(RH_SERENADE_WARP_LOC, Text(warpSerenadeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpSerenadeText));
|
||||
std::string warpRequiemText;
|
||||
SaveManager::Instance->LoadData("warpRequiemText", warpRequiemText);
|
||||
randoContext->AddHint(RH_REQUIEM_WARP_LOC, Text(warpRequiemText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpRequiemText));
|
||||
std::string warpNocturneText;
|
||||
SaveManager::Instance->LoadData("warpNocturneText", warpNocturneText);
|
||||
randoContext->AddHint(RH_NOCTURNE_WARP_LOC, Text(warpNocturneText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpNocturneText));
|
||||
std::string warpPreludeText;
|
||||
SaveManager::Instance->LoadData("warpPreludeText", warpPreludeText);
|
||||
randoContext->AddHint(RH_PRELUDE_WARP_LOC, Text(warpPreludeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text(warpPreludeText));
|
||||
|
||||
SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems);
|
||||
|
||||
@@ -244,8 +288,6 @@ void SaveManager::LoadRandomizerVersion2() {
|
||||
|
||||
std::shared_ptr<Randomizer> randomizer = OTRGlobals::Instance->gRandomizer;
|
||||
|
||||
randomizer->LoadRandomizerSettings("");
|
||||
|
||||
size_t merchantPricesSize = 0;
|
||||
SaveManager::Instance->LoadData("merchantPricesSize", merchantPricesSize);
|
||||
|
||||
@@ -255,76 +297,194 @@ void SaveManager::LoadRandomizerVersion2() {
|
||||
SaveManager::Instance->LoadData("check", rc);
|
||||
uint32_t price;
|
||||
SaveManager::Instance->LoadData("price", price);
|
||||
randomizer->merchantPrices[rc] = price;
|
||||
randoContext->GetItemLocation(rc)->SetCustomPrice(price);
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->LoadData("masterQuestDungeonCount", gSaveContext.mqDungeonCount, (uint8_t)0);
|
||||
size_t mqDungeonCount;
|
||||
SaveManager::Instance->LoadData("masterQuestDungeonCount", mqDungeonCount, (size_t)0);
|
||||
|
||||
OTRGlobals::Instance->gRandomizer->masterQuestDungeons.clear();
|
||||
SaveManager::Instance->LoadArray("masterQuestDungeons", gSaveContext.mqDungeonCount, [&](size_t i) {
|
||||
randoContext->GetDungeons()->ClearAllMQ();
|
||||
SaveManager::Instance->LoadArray("masterQuestDungeons", mqDungeonCount, [&](size_t i) {
|
||||
uint16_t scene;
|
||||
SaveManager::Instance->LoadData("", scene);
|
||||
randomizer->masterQuestDungeons.emplace(scene);
|
||||
randoContext->GetDungeons()->GetDungeonFromScene(SceneID(scene))->SetMQ();
|
||||
});
|
||||
}
|
||||
|
||||
void SaveManager::LoadRandomizerVersion3() {
|
||||
auto randoContext = Rando::Context::GetInstance();
|
||||
SaveManager::Instance->LoadArray("itemLocations", RC_MAX, [&](size_t i) {
|
||||
SaveManager::Instance->LoadStruct("", [&]() {
|
||||
SaveManager::Instance->LoadData("rgID", randoContext->GetItemLocation(i)->RefPlacedItem());
|
||||
RandomizerGet rg = RG_NONE;
|
||||
SaveManager::Instance->LoadData("fakeRgID", rg, RG_NONE);
|
||||
if (rg != RG_NONE) {
|
||||
randoContext->overrides[static_cast<RandomizerCheck>(i)] =
|
||||
Rando::ItemOverride(static_cast<RandomizerCheck>(i), rg);
|
||||
SaveManager::Instance->LoadStruct("trickName", [&]() {
|
||||
SaveManager::Instance->LoadData(
|
||||
"english", randoContext->overrides[static_cast<RandomizerCheck>(i)].GetTrickName().english);
|
||||
SaveManager::Instance->LoadData(
|
||||
"french", randoContext->overrides[static_cast<RandomizerCheck>(i)].GetTrickName().french);
|
||||
});
|
||||
}
|
||||
uint16_t price = 0;
|
||||
SaveManager::Instance->LoadData("price", price, (uint16_t)0);
|
||||
if (price > 0) {
|
||||
// Technically an item with a custom price (scrub/shopsanity) could have
|
||||
// a 0 rupee price, meaning it would not be loaded after the first save and
|
||||
// disappear from the save file. However, this is fine, as the default price on
|
||||
// all ItemLocations is 0 anyway.
|
||||
randoContext->GetItemLocation(i)->SetCustomPrice(price);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
auto entranceCtx = randoContext->GetEntranceShuffler();
|
||||
SaveManager::Instance->LoadArray("entrances", ARRAY_COUNT(entranceCtx->entranceOverrides), [&](size_t i) {
|
||||
SaveManager::Instance->LoadStruct("", [&]() {
|
||||
SaveManager::Instance->LoadData("index", entranceCtx->entranceOverrides[i].index);
|
||||
SaveManager::Instance->LoadData("destination", entranceCtx->entranceOverrides[i].destination);
|
||||
SaveManager::Instance->LoadData("blueWarp", entranceCtx->entranceOverrides[i].blueWarp);
|
||||
SaveManager::Instance->LoadData("override", entranceCtx->entranceOverrides[i].override);
|
||||
SaveManager::Instance->LoadData("overrideDestination",
|
||||
entranceCtx->entranceOverrides[i].overrideDestination);
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->LoadArray("seed", randoContext->hashIconIndexes.size(), [&](size_t i) {
|
||||
SaveManager::Instance->LoadData("", randoContext->hashIconIndexes[i]);
|
||||
});
|
||||
|
||||
std::string inputSeed;
|
||||
SaveManager::Instance->LoadData("inputSeed", inputSeed);
|
||||
randoContext->GetSettings()->SetSeedString(inputSeed);
|
||||
|
||||
uint32_t finalSeed;
|
||||
SaveManager::Instance->LoadData("finalSeed", finalSeed);
|
||||
randoContext->GetSettings()->SetSeed(finalSeed);
|
||||
|
||||
SaveManager::Instance->LoadArray("randoSettings", RSK_MAX, [&](size_t i) {
|
||||
int value = 0;
|
||||
SaveManager::Instance->LoadData("", value);
|
||||
randoContext->GetOption(RandomizerSettingKey(i)).SetSelectedIndex(value);
|
||||
});
|
||||
|
||||
SaveManager::Instance->LoadArray("hintLocations", RH_MAX, [&](size_t i) {
|
||||
SaveManager::Instance->LoadStruct("", [&]() {
|
||||
RandomizerHintKey rhk = RH_NONE;
|
||||
SaveManager::Instance->LoadData("hintKey", rhk);
|
||||
std::string english, french;
|
||||
SaveManager::Instance->LoadStruct("hintText", [&]() {
|
||||
SaveManager::Instance->LoadData("english", english);
|
||||
SaveManager::Instance->LoadData("french", french);
|
||||
// TODO: German Hint Translations
|
||||
});
|
||||
RandomizerCheck rc = RC_UNKNOWN_CHECK;
|
||||
SaveManager::Instance->LoadData("hintedCheck", rc);
|
||||
HintType ht = HINT_TYPE_STATIC;
|
||||
SaveManager::Instance->LoadData("hintType", ht);
|
||||
std::string englishRegion, frenchRegion;
|
||||
SaveManager::Instance->LoadStruct("hintedRegion", [&]() {
|
||||
SaveManager::Instance->LoadData("english", englishRegion);
|
||||
SaveManager::Instance->LoadData("french", frenchRegion);
|
||||
});
|
||||
randoContext->AddHint(rhk, Text(english, french, english), rc, ht, Text(englishRegion, frenchRegion, englishRegion));
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems);
|
||||
|
||||
SaveManager::Instance->LoadData("triforcePiecesCollected", gSaveContext.triforcePiecesCollected);
|
||||
|
||||
SaveManager::Instance->LoadData("pendingIceTrapCount", gSaveContext.pendingIceTrapCount);
|
||||
|
||||
std::shared_ptr<Randomizer> randomizer = OTRGlobals::Instance->gRandomizer;
|
||||
|
||||
size_t mqDungeonCount;
|
||||
SaveManager::Instance->LoadData("masterQuestDungeonCount", mqDungeonCount, (size_t)0);
|
||||
|
||||
randoContext->GetDungeons()->ClearAllMQ();
|
||||
SaveManager::Instance->LoadArray("masterQuestDungeons", mqDungeonCount, [&](size_t i) {
|
||||
size_t dungeonId;
|
||||
SaveManager::Instance->LoadData("", dungeonId);
|
||||
randoContext->GetDungeon(dungeonId)->SetMQ();
|
||||
});
|
||||
|
||||
randoContext->GetTrials()->SkipAll();
|
||||
SaveManager::Instance->LoadArray("requiredTrials", randoContext->GetOption(RSK_TRIAL_COUNT).GetSelectedOptionIndex()+1, [&](size_t i) {
|
||||
size_t trialId;
|
||||
SaveManager::Instance->LoadData("", trialId);
|
||||
randoContext->GetTrial(trialId)->SetAsRequired();
|
||||
});
|
||||
}
|
||||
|
||||
void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool fullSave) {
|
||||
|
||||
if(saveContext->questId != QUEST_RANDOMIZER) return;
|
||||
auto randoContext = Rando::Context::GetInstance();
|
||||
|
||||
SaveManager::Instance->SaveArray("itemLocations", RC_MAX, [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("rgID", saveContext->itemLocations[i].get.rgID);
|
||||
SaveManager::Instance->SaveData("fakeRgID", saveContext->itemLocations[i].get.fakeRgID);
|
||||
SaveManager::Instance->SaveData("trickName", saveContext->itemLocations[i].get.trickName);
|
||||
SaveManager::Instance->SaveData("rgID", randoContext->GetItemLocation(i)->GetPlacedRandomizerGet());
|
||||
if (randoContext->GetItemLocation(i)->GetPlacedRandomizerGet() == RG_ICE_TRAP) {
|
||||
SaveManager::Instance->SaveData("fakeRgID", randoContext->overrides[static_cast<RandomizerCheck>(i)].LooksLike());
|
||||
SaveManager::Instance->SaveStruct("trickName", [&]() {
|
||||
SaveManager::Instance->SaveData("english", randoContext->overrides[static_cast<RandomizerCheck>(i)].GetTrickName().GetEnglish());
|
||||
SaveManager::Instance->SaveData("french", randoContext->overrides[static_cast<RandomizerCheck>(i)].GetTrickName().GetFrench());
|
||||
// TODO: German (trick names don't have german translations yet)
|
||||
});
|
||||
}
|
||||
if (randoContext->GetItemLocation(i)->HasCustomPrice()) {
|
||||
SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveArray("entrances", ARRAY_COUNT(saveContext->entranceOverrides), [&](size_t i) {
|
||||
auto entranceCtx = randoContext->GetEntranceShuffler();
|
||||
SaveManager::Instance->SaveArray("entrances", ARRAY_COUNT(entranceCtx->entranceOverrides), [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("index", saveContext->entranceOverrides[i].index);
|
||||
SaveManager::Instance->SaveData("destination", saveContext->entranceOverrides[i].destination);
|
||||
SaveManager::Instance->SaveData("blueWarp", saveContext->entranceOverrides[i].blueWarp);
|
||||
SaveManager::Instance->SaveData("override", saveContext->entranceOverrides[i].override);
|
||||
SaveManager::Instance->SaveData("overrideDestination", saveContext->entranceOverrides[i].overrideDestination);
|
||||
SaveManager::Instance->SaveData("index", entranceCtx->entranceOverrides[i].index);
|
||||
SaveManager::Instance->SaveData("destination", entranceCtx->entranceOverrides[i].destination);
|
||||
SaveManager::Instance->SaveData("blueWarp", entranceCtx->entranceOverrides[i].blueWarp);
|
||||
SaveManager::Instance->SaveData("override", entranceCtx->entranceOverrides[i].override);
|
||||
SaveManager::Instance->SaveData("overrideDestination", entranceCtx->entranceOverrides[i].overrideDestination);
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveArray("seed", ARRAY_COUNT(saveContext->seedIcons), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->seedIcons[i]);
|
||||
SaveManager::Instance->SaveArray("seed", randoContext->hashIconIndexes.size(), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", randoContext->hashIconIndexes[i]);
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveData("inputSeed", saveContext->inputSeed);
|
||||
SaveManager::Instance->SaveData("inputSeed", randoContext->GetSettings()->GetSeedString());
|
||||
|
||||
SaveManager::Instance->SaveData("finalSeed", saveContext->finalSeed);
|
||||
SaveManager::Instance->SaveData("finalSeed", randoContext->GetSettings()->GetSeed());
|
||||
|
||||
SaveManager::Instance->SaveArray("randoSettings", RSK_MAX, [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", saveContext->randoSettings[i].value);
|
||||
SaveManager::Instance->SaveData("", randoContext->GetOption((RandomizerSettingKey(i))).GetSelectedOptionIndex());
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveArray("hintLocations", ARRAY_COUNT(saveContext->hintLocations), [&](size_t i) {
|
||||
SaveManager::Instance->SaveArray("hintLocations", RH_MAX, [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("check", saveContext->hintLocations[i].check);
|
||||
SaveManager::Instance->SaveData("hintText", saveContext->hintLocations[i].hintText);
|
||||
auto hint = randoContext->GetHint(RandomizerHintKey(i));
|
||||
SaveManager::Instance->SaveData("hintKey", RandomizerHintKey(i));
|
||||
SaveManager::Instance->SaveStruct("hintText", [&]() {
|
||||
SaveManager::Instance->SaveData("english", hint->GetText().GetEnglish());
|
||||
SaveManager::Instance->SaveData("french", hint->GetText().GetFrench());
|
||||
SaveManager::Instance->SaveData("german", hint->GetText().GetEnglish());
|
||||
// TODO: German Translation of hints
|
||||
});
|
||||
SaveManager::Instance->SaveData("hintedCheck", hint->GetHintedLocation());
|
||||
SaveManager::Instance->SaveData("hintType", hint->GetHintType());
|
||||
SaveManager::Instance->SaveStruct("hintedRegion", [&]() {
|
||||
SaveManager::Instance->SaveData("english", hint->GetHintedRegionText().GetEnglish());
|
||||
SaveManager::Instance->SaveData("french", hint->GetHintedRegionText().GetFrench());
|
||||
SaveManager::Instance->SaveData("german", hint->GetHintedRegionText().GetEnglish());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveData("childAltarText", saveContext->childAltarText);
|
||||
SaveManager::Instance->SaveData("adultAltarText", saveContext->adultAltarText);
|
||||
SaveManager::Instance->SaveData("ganonHintText", saveContext->ganonHintText);
|
||||
SaveManager::Instance->SaveData("ganonText", saveContext->ganonText);
|
||||
SaveManager::Instance->SaveData("dampeText", saveContext->dampeText);
|
||||
SaveManager::Instance->SaveData("gregHintText", saveContext->gregHintText);
|
||||
SaveManager::Instance->SaveData("sheikText", saveContext->sheikText);
|
||||
SaveManager::Instance->SaveData("sariaText", saveContext->sariaText);
|
||||
SaveManager::Instance->SaveData("warpMinuetText", saveContext->warpMinuetText);
|
||||
SaveManager::Instance->SaveData("warpBoleroText", saveContext->warpBoleroText);
|
||||
SaveManager::Instance->SaveData("warpSerenadeText", saveContext->warpSerenadeText);
|
||||
SaveManager::Instance->SaveData("warpRequiemText", saveContext->warpRequiemText);
|
||||
SaveManager::Instance->SaveData("warpNocturneText", saveContext->warpNocturneText);
|
||||
SaveManager::Instance->SaveData("warpPreludeText", saveContext->warpPreludeText);
|
||||
|
||||
SaveManager::Instance->SaveData("adultTradeItems", saveContext->adultTradeItems);
|
||||
|
||||
SaveManager::Instance->SaveData("triforcePiecesCollected", saveContext->triforcePiecesCollected);
|
||||
@@ -333,27 +493,18 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f
|
||||
|
||||
std::shared_ptr<Randomizer> randomizer = OTRGlobals::Instance->gRandomizer;
|
||||
|
||||
std::vector<std::pair<RandomizerCheck, u16>> merchantPrices;
|
||||
for (const auto & [ check, price ] : randomizer->merchantPrices) {
|
||||
merchantPrices.push_back(std::make_pair(check, price));
|
||||
}
|
||||
SaveManager::Instance->SaveData("masterQuestDungeonCount", randoContext->GetDungeons()->CountMQ());
|
||||
|
||||
SaveManager::Instance->SaveData("merchantPricesSize", merchantPrices.size());
|
||||
SaveManager::Instance->SaveArray("merchantPrices", merchantPrices.size(), [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("check", merchantPrices[i].first);
|
||||
SaveManager::Instance->SaveData("price", merchantPrices[i].second);
|
||||
});
|
||||
SaveManager::Instance->SaveArray("masterQuestDungeons", randoContext->GetDungeons()->GetDungeonListSize(), [&](size_t i) {
|
||||
if (randoContext->GetDungeon(i)->IsMQ()) {
|
||||
SaveManager::Instance->SaveData("", i);
|
||||
}
|
||||
});
|
||||
|
||||
SaveManager::Instance->SaveData("masterQuestDungeonCount", saveContext->mqDungeonCount);
|
||||
|
||||
std::vector<uint16_t> masterQuestDungeons;
|
||||
for (const auto scene : randomizer->masterQuestDungeons) {
|
||||
masterQuestDungeons.push_back(scene);
|
||||
}
|
||||
SaveManager::Instance->SaveArray("masterQuestDungeons", masterQuestDungeons.size(), [&](size_t i) {
|
||||
SaveManager::Instance->SaveData("", masterQuestDungeons[i]);
|
||||
SaveManager::Instance->SaveArray("requiredTrials", randoContext->GetTrials()->GetTrialListSize(), [&](size_t i) {
|
||||
if (randoContext->GetTrial(i)->IsRequired()) {
|
||||
SaveManager::Instance->SaveData("", i);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -436,17 +587,18 @@ void SaveManager::InitMeta(int fileNum) {
|
||||
fileMetaInfo[fileNum].gregFound = Flags_GetRandomizerInf(RAND_INF_GREG_FOUND);
|
||||
fileMetaInfo[fileNum].defense = gSaveContext.inventory.defenseHearts;
|
||||
fileMetaInfo[fileNum].health = gSaveContext.health;
|
||||
auto randoContext = Rando::Context::GetInstance();
|
||||
|
||||
for (int i = 0; i < ARRAY_COUNT(fileMetaInfo[fileNum].seedHash); i++) {
|
||||
fileMetaInfo[fileNum].seedHash[i] = gSaveContext.seedIcons[i];
|
||||
for (int i = 0; i < ARRAY_COUNT(fileMetaInfo[fileNum].seedHash); i++) {
|
||||
fileMetaInfo[fileNum].seedHash[i] = randoContext->hashIconIndexes[i];
|
||||
}
|
||||
|
||||
fileMetaInfo[fileNum].randoSave = IS_RANDO;
|
||||
// If the file is marked as a Master Quest file or if we're randomized and have at least one master quest dungeon, we need the mq otr.
|
||||
fileMetaInfo[fileNum].requiresMasterQuest = IS_MASTER_QUEST || (IS_RANDO && gSaveContext.mqDungeonCount > 0);
|
||||
fileMetaInfo[fileNum].requiresMasterQuest = IS_MASTER_QUEST || (IS_RANDO && randoContext->GetDungeons()->CountMQ() > 0);
|
||||
// If the file is not marked as Master Quest, it could still theoretically be a rando save with all 12 MQ dungeons, in which case
|
||||
// we don't actually require a vanilla OTR.
|
||||
fileMetaInfo[fileNum].requiresOriginal = !IS_MASTER_QUEST && (!IS_RANDO || gSaveContext.mqDungeonCount < 12);
|
||||
fileMetaInfo[fileNum].requiresOriginal = !IS_MASTER_QUEST && (!IS_RANDO || randoContext->GetDungeons()->CountMQ() < 12);
|
||||
|
||||
fileMetaInfo[fileNum].buildVersionMajor = gSaveContext.sohStats.buildVersionMajor;
|
||||
fileMetaInfo[fileNum].buildVersionMinor = gSaveContext.sohStats.buildVersionMinor;
|
||||
|
||||
@@ -157,6 +157,7 @@ class SaveManager {
|
||||
|
||||
static void LoadRandomizerVersion1();
|
||||
static void LoadRandomizerVersion2();
|
||||
static void LoadRandomizerVersion3();
|
||||
static void SaveRandomizer(SaveContext* saveContext, int sectionID, bool fullSave);
|
||||
|
||||
static void LoadBaseVersion1();
|
||||
|
||||
@@ -1472,6 +1472,14 @@ extern std::shared_ptr<CheckTracker::CheckTrackerSettingsWindow> mCheckTrackerSe
|
||||
|
||||
void DrawRandomizerMenu() {
|
||||
if (ImGui::BeginMenu("Randomizer")) {
|
||||
UIWidgets::EnhancementCheckbox("Plando Mode", "gPlandoMode");
|
||||
UIWidgets::Tooltip(
|
||||
"When dropping a spoiler file on the game window, parse the full spoiler file instead of just the "
|
||||
"necessary "
|
||||
"parts to regenerate a seed.\n\nKeep in mind if you do this, all custom text will only be available in the "
|
||||
"language present in the spoilerfile. You can use this to edit a previously generated spoilerfile that has "
|
||||
"been edited with custom hint text and item locations. May be useful for debugging.");
|
||||
UIWidgets::PaddedSeparator();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
||||
|
||||
@@ -221,8 +221,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
||||
|
||||
gSaveContext.n64ddFlag = fileChooseCtx->n64ddFlag;
|
||||
|
||||
if (fileChooseCtx->questType[fileChooseCtx->buttonIndex] == QUEST_RANDOMIZER &&
|
||||
strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0) {
|
||||
if (Randomizer_IsSeedGenerated()) {
|
||||
gSaveContext.questId = QUEST_RANDOMIZER;
|
||||
|
||||
Randomizer_InitSaveFile();
|
||||
|
||||
@@ -65,6 +65,7 @@ typedef enum {
|
||||
CM_BOSS_RUSH_MENU,
|
||||
CM_START_BOSS_RUSH_MENU,
|
||||
CM_BOSS_RUSH_TO_QUEST,
|
||||
CM_GENERATE_SEED,
|
||||
} ConfigMode;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -671,13 +671,6 @@ static void DrawMoreInfo(FileChooseContext* this, s16 fileIndex, u8 alpha) {
|
||||
void Sram_InitDebugSave(void);
|
||||
void Sram_InitBossRushSave();
|
||||
|
||||
u8 hasRandomizerQuest() {
|
||||
if (strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileChoose_DrawTextureI8(GraphicsContext* gfxCtx, const void* texture, s16 texWidth, s16 texHeight, s16 rectLeft, s16 rectTop,
|
||||
s16 rectWidth, s16 rectHeight, s16 dsdx, s16 dtdy) {
|
||||
OPEN_DISPS(gfxCtx);
|
||||
@@ -953,17 +946,15 @@ void SpriteDraw(FileChooseContext* this, Sprite* sprite, int left, int top, int
|
||||
CLOSE_DISPS(this->state.gfxCtx);
|
||||
}
|
||||
|
||||
bool fileSelectSpoilerFileLoaded = false;
|
||||
|
||||
void DrawSeedHashSprites(FileChooseContext* this) {
|
||||
OPEN_DISPS(this->state.gfxCtx);
|
||||
gDPPipeSync(POLY_OPA_DISP++);
|
||||
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
||||
|
||||
// Draw icons on the main menu, when a rando file is selected, and when quest selection is set to rando
|
||||
if ((this->configMode == CM_MAIN_MENU &&
|
||||
(this->selectMode != SM_CONFIRM_FILE || Save_GetSaveMetaInfo(this->selectedFileIndex)->randoSave == 1)) ||
|
||||
(this->configMode == CM_QUEST_MENU && this->questType[this->buttonIndex] == QUEST_RANDOMIZER)) {
|
||||
// Draw icons on the main menu, when a rando file is selected, and on name entry when quest selection is set to rando
|
||||
if (this->configMode == CM_MAIN_MENU &&
|
||||
(this->selectMode != SM_CONFIRM_FILE || Save_GetSaveMetaInfo(this->selectedFileIndex)->randoSave == 1)) {
|
||||
|
||||
if (this->fileInfoAlpha[this->selectedFileIndex] > 0) {
|
||||
// Use file info alpha to match fading
|
||||
@@ -972,30 +963,32 @@ void DrawSeedHashSprites(FileChooseContext* this) {
|
||||
u16 xStart = 64;
|
||||
// Draw Seed Icons for specific file
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
if (Save_GetSaveMetaInfo(this->selectedFileIndex)->randoSave == 1) {
|
||||
SpriteLoad(this, GetSeedTexture(Save_GetSaveMetaInfo(this->selectedFileIndex)->seedHash[i]));
|
||||
SpriteDraw(this, GetSeedTexture(Save_GetSaveMetaInfo(this->selectedFileIndex)->seedHash[i]),
|
||||
xStart + (40 * i), 10, 24, 24);
|
||||
}
|
||||
SpriteLoad(this, GetSeedTexture(Save_GetSaveMetaInfo(this->selectedFileIndex)->seedHash[i]));
|
||||
SpriteDraw(this, GetSeedTexture(Save_GetSaveMetaInfo(this->selectedFileIndex)->seedHash[i]),
|
||||
xStart + (40 * i), 10, 24, 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw Seed Icons for spoiler log:
|
||||
// 1. On Name Entry if a rando seed has been generated
|
||||
// 2. On Quest Menu if a spoiler has been dropped and the Randomizer quest option is currently hovered.
|
||||
if ((Randomizer_IsSeedGenerated() ||
|
||||
(strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0 && Randomizer_IsSpoilerLoaded())) &&
|
||||
((this->configMode == CM_NAME_ENTRY && gSaveContext.questId == QUEST_RANDOMIZER) ||
|
||||
(this->configMode == CM_QUEST_MENU && this->questType[this->buttonIndex] == QUEST_RANDOMIZER))) {
|
||||
// Fade top seed icons based on main menu fade and if save supports rando
|
||||
u8 alpha = MAX(this->optionButtonAlpha, Save_GetSaveMetaInfo(this->selectedFileIndex)->randoSave == 1 ? 0xFF : 0);
|
||||
u8 alpha =
|
||||
MAX(this->optionButtonAlpha, Save_GetSaveMetaInfo(this->selectedFileIndex)->randoSave == 1 ? 0xFF : 0);
|
||||
if (alpha >= 200) {
|
||||
alpha = 0xFF;
|
||||
}
|
||||
|
||||
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0xFF, 0xFF, 0xFF, alpha);
|
||||
|
||||
// Draw Seed Icons for spoiler log
|
||||
if (this->configMode == CM_QUEST_MENU && this->questType[this->buttonIndex] == QUEST_RANDOMIZER &&
|
||||
strnlen(CVarGetString("gSpoilerLog", ""), 1) != 0 && fileSelectSpoilerFileLoaded) {
|
||||
u16 xStart = 64;
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
SpriteLoad(this, GetSeedTexture(gSaveContext.seedIcons[i]));
|
||||
SpriteDraw(this, GetSeedTexture(gSaveContext.seedIcons[i]), xStart + (40 * i), 10, 24, 24);
|
||||
}
|
||||
u16 xStart = 64;
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
SpriteLoad(this, GetSeedTexture(GetSeedIconIndex(i)));
|
||||
SpriteDraw(this, GetSeedTexture(GetSeedIconIndex(i)), xStart + (40 * i), 10, 24, 24);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1012,7 +1005,7 @@ void FileChoose_UpdateRandomizer() {
|
||||
func_800F5E18(SEQ_PLAYER_BGM_MAIN, NA_BGM_HORSE, 0, 7, 1);
|
||||
return;
|
||||
} else if (CVarGetInteger("gRandoGenerating", 0) == 0 && generating) {
|
||||
if (SpoilerFileExists(CVarGetString("gSpoilerLog", ""))) {
|
||||
if (SpoilerFileExists(CVarGetString("gSpoilerLog", "")) || Randomizer_IsSeedGenerated()) {
|
||||
Audio_PlayFanfare(NA_BGM_HORSE_GOAL);
|
||||
} else {
|
||||
func_80078884(NA_SE_SY_OCARINA_ERROR);
|
||||
@@ -1026,31 +1019,15 @@ void FileChoose_UpdateRandomizer() {
|
||||
|
||||
if (!SpoilerFileExists(CVarGetString("gSpoilerLog", ""))) {
|
||||
CVarSetString("gSpoilerLog", "");
|
||||
fileSelectSpoilerFileLoaded = false;
|
||||
}
|
||||
|
||||
if ((CVarGetInteger("gNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0) ||
|
||||
(!fileSelectSpoilerFileLoaded && SpoilerFileExists(CVarGetString("gSpoilerLog", "")))) {
|
||||
if (CVarGetInteger("gNewFileDropped", 0) != 0) {
|
||||
CVarSetString("gSpoilerLog", CVarGetString("gDroppedFile", "None"));
|
||||
}
|
||||
bool silent = true;
|
||||
if ((CVarGetInteger("gNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0)) {
|
||||
silent = false;
|
||||
}
|
||||
if ((CVarGetInteger("gNewFileDropped", 0) != 0)) {
|
||||
CVarSetString("gSpoilerLog", CVarGetString("gDroppedFile", ""));
|
||||
CVarSetInteger("gNewSeedGenerated", 0);
|
||||
CVarSetInteger("gNewFileDropped", 0);
|
||||
CVarSetString("gDroppedFile", "");
|
||||
fileSelectSpoilerFileLoaded = false;
|
||||
const char* fileLoc = CVarGetString("gSpoilerLog", "");
|
||||
Randomizer_LoadSettings(fileLoc);
|
||||
Randomizer_LoadHintLocations(fileLoc);
|
||||
Randomizer_LoadRequiredTrials(fileLoc);
|
||||
Randomizer_LoadItemLocations(fileLoc, silent);
|
||||
Randomizer_LoadMerchantMessages(fileLoc);
|
||||
Randomizer_LoadMasterQuestDungeons(fileLoc);
|
||||
Randomizer_LoadEntranceOverrides(fileLoc, silent);
|
||||
fileSelectSpoilerFileLoaded = true;
|
||||
Randomizer_ParseSpoiler(fileLoc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1300,8 +1277,10 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) {
|
||||
this->prevConfigMode = this->configMode;
|
||||
this->configMode = CM_ROTATE_TO_BOSS_RUSH_MENU;
|
||||
return;
|
||||
} else if (this->questType[this->buttonIndex] == QUEST_RANDOMIZER && !hasRandomizerQuest()) {
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
} else if (this->questType[this->buttonIndex] == QUEST_RANDOMIZER) {
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
this->prevConfigMode = this->configMode;
|
||||
this->configMode = CM_GENERATE_SEED;
|
||||
} else {
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||
osSyncPrintf("Selected Dungeon Quest: %d\n", IS_MASTER_QUEST);
|
||||
@@ -1330,6 +1309,33 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) {
|
||||
}
|
||||
}
|
||||
|
||||
void FileChoose_GenerateRandoSeed(GameState* thisx) {
|
||||
FileChooseContext* this = (FileChooseContext*)thisx;
|
||||
FileChoose_UpdateRandomizer();
|
||||
if (Randomizer_IsSeedGenerated() || Randomizer_IsPlandoLoaded()) {
|
||||
static u8 emptyName[] = { 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E };
|
||||
static u8 linkName[] = { 0x15, 0x2C, 0x31, 0x2E, 0x3E, 0x3E, 0x3E, 0x3E };
|
||||
this->prevConfigMode = this->configMode;
|
||||
this->configMode = CM_ROTATE_TO_NAME_ENTRY;
|
||||
this->logoAlpha = 0;
|
||||
CVarSetInteger("gOnFileSelectNameEntry", 1);
|
||||
this->kbdButton = FS_KBD_BTN_NONE;
|
||||
this->charPage = FS_CHAR_PAGE_ENG;
|
||||
this->kbdX = 0;
|
||||
this->kbdY = 0;
|
||||
this->charIndex = 0;
|
||||
this->charBgAlpha = 0;
|
||||
this->newFileNameCharCount = CVarGetInteger("gLinkDefaultName", 0) ? 4 : 0;
|
||||
this->nameEntryBoxPosX = 120;
|
||||
this->nameEntryBoxAlpha = 0;
|
||||
memcpy(Save_GetSaveMetaInfo(this->buttonIndex)->playerName,
|
||||
CVarGetInteger("gLinkDefaultName", 0) ? &linkName : &emptyName, 8);
|
||||
return;
|
||||
} else {
|
||||
Randomizer_GenerateSeed();
|
||||
}
|
||||
}
|
||||
|
||||
static s8 sLastBossRushOptionIndex = -1;
|
||||
static s8 sLastBossRushOptionValue = -1;
|
||||
|
||||
@@ -1562,6 +1568,7 @@ static void (*gConfigModeUpdateFuncs[])(GameState*) = {
|
||||
FileChoose_RotateToMain, FileChoose_RotateToQuest,
|
||||
FileChoose_RotateToBossRush, FileChoose_UpdateBossRushMenu,
|
||||
FileChoose_StartBossRushMenu, FileChoose_RotateToQuest,
|
||||
FileChoose_GenerateRandoSeed,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2161,6 +2168,7 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
|
||||
case CM_QUEST_TO_MAIN:
|
||||
case CM_NAME_ENTRY_TO_QUEST_MENU:
|
||||
case CM_ROTATE_TO_BOSS_RUSH_MENU:
|
||||
case CM_GENERATE_SEED:
|
||||
tex = FileChoose_GetQuestChooseTitleTexName(gSaveContext.language);
|
||||
break;
|
||||
case CM_BOSS_RUSH_MENU:
|
||||
@@ -2174,6 +2182,7 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
|
||||
}
|
||||
|
||||
OPEN_DISPS(this->state.gfxCtx);
|
||||
DrawSeedHashSprites(this);
|
||||
|
||||
// draw title label
|
||||
gDPPipeSync(POLY_OPA_DISP++);
|
||||
@@ -2189,32 +2198,34 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
|
||||
|
||||
// draw next title label
|
||||
if ((this->configMode == CM_QUEST_MENU) || (this->configMode == CM_START_QUEST_MENU) ||
|
||||
this->configMode == CM_NAME_ENTRY_TO_QUEST_MENU) {
|
||||
this->configMode == CM_NAME_ENTRY_TO_QUEST_MENU || this->configMode == CM_GENERATE_SEED) {
|
||||
// draw control stick prompts.
|
||||
Gfx_SetupDL_39Opa(this->state.gfxCtx);
|
||||
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
||||
gDPLoadTextureBlock(POLY_OPA_DISP++, gArrowCursorTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 24, 0,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOMASK, G_TX_NOLOD,
|
||||
G_TX_NOLOD);
|
||||
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickLeftPrompt.arrowColorR,
|
||||
this->stickLeftPrompt.arrowColorG, this->stickLeftPrompt.arrowColorB,
|
||||
this->stickLeftPrompt.arrowColorA, this->stickLeftPrompt.arrowTexX,
|
||||
this->stickLeftPrompt.arrowTexY, this->stickLeftPrompt.z, 0, 0, -1.0f, 1.0f);
|
||||
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickRightPrompt.arrowColorR,
|
||||
this->stickRightPrompt.arrowColorG, this->stickRightPrompt.arrowColorB,
|
||||
this->stickRightPrompt.arrowColorA, this->stickRightPrompt.arrowTexX,
|
||||
this->stickRightPrompt.arrowTexY, this->stickRightPrompt.z, 0, 0, 1.0f, 1.0f);
|
||||
gDPLoadTextureBlock(POLY_OPA_DISP++, gControlStickTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, 0,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOMASK, G_TX_NOLOD,
|
||||
G_TX_NOLOD);
|
||||
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickLeftPrompt.stickColorR,
|
||||
this->stickLeftPrompt.stickColorG, this->stickLeftPrompt.stickColorB,
|
||||
this->stickLeftPrompt.stickColorA, this->stickLeftPrompt.stickTexX,
|
||||
this->stickLeftPrompt.stickTexY, this->stickLeftPrompt.z, 0, 0, -1.0f, 1.0f);
|
||||
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickRightPrompt.stickColorR,
|
||||
this->stickRightPrompt.stickColorG, this->stickRightPrompt.stickColorB,
|
||||
this->stickRightPrompt.stickColorA, this->stickRightPrompt.stickTexX,
|
||||
this->stickRightPrompt.stickTexY, this->stickRightPrompt.z, 0, 0, 1.0f, 1.0f);
|
||||
if (this->configMode != CM_GENERATE_SEED) {
|
||||
Gfx_SetupDL_39Opa(this->state.gfxCtx);
|
||||
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
||||
gDPLoadTextureBlock(POLY_OPA_DISP++, gArrowCursorTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 24, 0,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOMASK, G_TX_NOLOD,
|
||||
G_TX_NOLOD);
|
||||
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickLeftPrompt.arrowColorR,
|
||||
this->stickLeftPrompt.arrowColorG, this->stickLeftPrompt.arrowColorB,
|
||||
this->stickLeftPrompt.arrowColorA, this->stickLeftPrompt.arrowTexX,
|
||||
this->stickLeftPrompt.arrowTexY, this->stickLeftPrompt.z, 0, 0, -1.0f, 1.0f);
|
||||
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickRightPrompt.arrowColorR,
|
||||
this->stickRightPrompt.arrowColorG, this->stickRightPrompt.arrowColorB,
|
||||
this->stickRightPrompt.arrowColorA, this->stickRightPrompt.arrowTexX,
|
||||
this->stickRightPrompt.arrowTexY, this->stickRightPrompt.z, 0, 0, 1.0f, 1.0f);
|
||||
gDPLoadTextureBlock(POLY_OPA_DISP++, gControlStickTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, 0,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOMASK, G_TX_NOLOD,
|
||||
G_TX_NOLOD);
|
||||
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickLeftPrompt.stickColorR,
|
||||
this->stickLeftPrompt.stickColorG, this->stickLeftPrompt.stickColorB,
|
||||
this->stickLeftPrompt.stickColorA, this->stickLeftPrompt.stickTexX,
|
||||
this->stickLeftPrompt.stickTexY, this->stickLeftPrompt.z, 0, 0, -1.0f, 1.0f);
|
||||
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickRightPrompt.stickColorR,
|
||||
this->stickRightPrompt.stickColorG, this->stickRightPrompt.stickColorB,
|
||||
this->stickRightPrompt.stickColorA, this->stickRightPrompt.stickTexX,
|
||||
this->stickRightPrompt.stickTexY, this->stickRightPrompt.z, 0, 0, 1.0f, 1.0f);
|
||||
}
|
||||
switch (this->questType[this->buttonIndex]) {
|
||||
case QUEST_NORMAL:
|
||||
default:
|
||||
@@ -2233,11 +2244,10 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
|
||||
break;
|
||||
|
||||
case QUEST_RANDOMIZER:
|
||||
DrawSeedHashSprites(this);
|
||||
if (hasRandomizerQuest()) {
|
||||
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->logoAlpha);
|
||||
if (this->configMode == CM_GENERATE_SEED) {
|
||||
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->logoAlpha / 2);
|
||||
} else {
|
||||
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0x40, 0x40, 0x40, this->logoAlpha);
|
||||
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->logoAlpha);
|
||||
}
|
||||
FileChoose_DrawTextureI8(this->state.gfxCtx, gTitleTheLegendOfTextTex, 72, 8, 156, 108, 72, 8, 1024, 1024);
|
||||
FileChoose_DrawTextureI8(this->state.gfxCtx, gTitleOcarinaOfTimeTMTextTex, 96, 8, 154, 163, 96, 8, 1024, 1024);
|
||||
@@ -2658,7 +2668,8 @@ void FileChoose_ConfigModeDraw(GameState* thisx) {
|
||||
// draw quest menu
|
||||
if ((this->configMode == CM_QUEST_MENU) || (this->configMode == CM_ROTATE_TO_QUEST_MENU) ||
|
||||
(this->configMode == CM_ROTATE_TO_NAME_ENTRY) || this->configMode == CM_QUEST_TO_MAIN ||
|
||||
this->configMode == CM_NAME_ENTRY_TO_QUEST_MENU || this->configMode == CM_ROTATE_TO_BOSS_RUSH_MENU) {
|
||||
this->configMode == CM_NAME_ENTRY_TO_QUEST_MENU || this->configMode == CM_ROTATE_TO_BOSS_RUSH_MENU ||
|
||||
this->configMode == CM_GENERATE_SEED) {
|
||||
// window
|
||||
gDPPipeSync(POLY_OPA_DISP++);
|
||||
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
||||
@@ -2964,13 +2975,8 @@ void FileChoose_LoadGame(GameState* thisx) {
|
||||
|
||||
this->state.running = false;
|
||||
|
||||
Randomizer_LoadSettings("");
|
||||
Randomizer_LoadHintLocations("");
|
||||
Randomizer_LoadItemLocations("", true);
|
||||
Randomizer_LoadRequiredTrials("");
|
||||
Randomizer_LoadMerchantMessages("");
|
||||
Randomizer_LoadMasterQuestDungeons("");
|
||||
Randomizer_LoadEntranceOverrides("", true);
|
||||
Randomizer_LoadHintMessages();
|
||||
Randomizer_LoadMerchantMessages();
|
||||
|
||||
gSaveContext.respawn[0].entranceIndex = -1;
|
||||
gSaveContext.respawnFlag = 0;
|
||||
@@ -3182,25 +3188,25 @@ void FileChoose_DrawRandoSaveVersionWarning(GameState* thisx) {
|
||||
|
||||
static const char* noRandoGeneratedText[] = {
|
||||
// English
|
||||
"No Randomizer seed currently available.\nGenerate one in the Randomizer Settings"
|
||||
"Open Randomizer Settings to change your settings,\nthen press A to generate a new seed"
|
||||
#if defined(__WIIU__) || defined(__SWITCH__)
|
||||
".",
|
||||
#else
|
||||
",\nor drop a spoiler log on the game window.",
|
||||
#endif
|
||||
// German
|
||||
"No Randomizer seed currently available.\nGenerate one in the Randomizer Settings"
|
||||
"Open Randomizer Settings to change your settings,\nthen press A to generate a new seed"
|
||||
#if defined(__WIIU__) || defined(__SWITCH__)
|
||||
".",
|
||||
#else
|
||||
",\nor drop a spoiler log on the game window.",
|
||||
#endif
|
||||
// French
|
||||
"Aucune Seed de Randomizer actuellement disponible.\nGénérez-en une dans les \"Randomizer Settings\""
|
||||
"Ouvrez le menu \"Randomizer Settings\" pour modifier\nvos paramètres, appuyez sur A pour générer\nune nouvelle seed"
|
||||
#if (defined(__WIIU__) || defined(__SWITCH__))
|
||||
"."
|
||||
#else
|
||||
"\nou glissez un spoilerlog sur la fenêtre du jeu."
|
||||
" ou glissez un spoilerlog sur la\nfenêtre du jeu."
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -3210,7 +3216,7 @@ void FileChoose_DrawNoRandoGeneratedWarning(GameState* thisx) {
|
||||
OPEN_DISPS(this->state.gfxCtx);
|
||||
|
||||
// Draw rando seed warning when build version doesn't match for Major or Minor number
|
||||
if (this->configMode == CM_QUEST_MENU && this->questType[this->buttonIndex] == QUEST_RANDOMIZER && !hasRandomizerQuest()) {
|
||||
if (this->configMode == CM_QUEST_MENU && this->questType[this->buttonIndex] == QUEST_RANDOMIZER && !(Randomizer_IsSeedGenerated() || Randomizer_IsSpoilerLoaded())) {
|
||||
uint8_t textAlpha = 225;
|
||||
uint8_t textboxAlpha = 170;
|
||||
float textboxScale = 0.7f;
|
||||
@@ -3223,12 +3229,18 @@ void FileChoose_DrawNoRandoGeneratedWarning(GameState* thisx) {
|
||||
uint16_t textboxWidth = 256 * textboxScale;
|
||||
uint16_t textboxHeight = 64 * textboxScale;
|
||||
uint8_t leftOffset = 72;
|
||||
uint8_t bottomOffset = 84;
|
||||
uint8_t bottomOffset = 132;
|
||||
uint8_t textVerticalOffset;
|
||||
#if defined(__WIIU__) || defined(__SWITCH__)
|
||||
textVerticalOffset = 127; // 2 lines
|
||||
textVerticalOffset = 80; // 2 lines
|
||||
if (gSaveContext.language == LANGUAGE_FRA) {
|
||||
textVerticalOffset = 75; // 3 lines
|
||||
}
|
||||
#else
|
||||
textVerticalOffset = 122; // 3 lines
|
||||
textVerticalOffset = 75; // 3 lines
|
||||
if (gSaveContext.language == LANGUAGE_FRA) {
|
||||
textVerticalOffset = 70; // 4 lines
|
||||
}
|
||||
#endif
|
||||
|
||||
Gfx_SetupDL_39Opa(this->state.gfxCtx);
|
||||
@@ -3664,7 +3676,6 @@ void FileChoose_Init(GameState* thisx) {
|
||||
this->questType[0] = MIN_QUEST;
|
||||
this->questType[1] = MIN_QUEST;
|
||||
this->questType[2] = MIN_QUEST;
|
||||
fileSelectSpoilerFileLoaded = false;
|
||||
isFastFileIdIncompatible = 0;
|
||||
CVarSetInteger("gOnFileSelectNameEntry", 0);
|
||||
|
||||
|
||||
@@ -375,6 +375,7 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
|
||||
this->newFileNameCharCount = 0;
|
||||
if (this->prevConfigMode == CM_QUEST_MENU) {
|
||||
this->configMode = CM_NAME_ENTRY_TO_QUEST_MENU;
|
||||
Randomizer_SetSeedGenerated(false);
|
||||
} else {
|
||||
this->configMode = CM_NAME_ENTRY_TO_MAIN;
|
||||
}
|
||||
@@ -457,6 +458,9 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
|
||||
this->configMode = CM_NAME_ENTRY_TO_MAIN;
|
||||
CVarSetInteger("gOnFileSelectNameEntry", 0);
|
||||
CVarSetInteger("gNewFileDropped", 0);
|
||||
Randomizer_SetSeedGenerated(false);
|
||||
Randomizer_SetSpoilerLoaded(false);
|
||||
Randomizer_SetPlandoLoaded(false);
|
||||
this->nameBoxAlpha[this->buttonIndex] = this->nameAlpha[this->buttonIndex] = 200;
|
||||
this->connectorAlpha[this->buttonIndex] = 255;
|
||||
func_800AA000(300.0f, 0xB4, 0x14, 0x64);
|
||||
|
||||
Reference in New Issue
Block a user