Merge branch 'develop' into ItemName

This commit is contained in:
Pepper0ni 2025-07-04 17:43:52 +01:00
commit b00f1994d6
89 changed files with 1203 additions and 1178 deletions

1
.gitignore vendored
View file

@ -457,3 +457,4 @@ soh/properties.h
# Tools # Tools
/clang-format /clang-format
/clang-format.exe /clang-format.exe
*.o2r

View file

@ -25,7 +25,7 @@ if (-not (Test-Path $clangFormatFilePath) -or ($currentVersion -ne $requiredVers
} }
$wc = New-Object net.webclient $wc = New-Object net.webclient
$wc.Downloadfile($url, $llvmInstallerPath) $wc.Downloadfile($url, $PSScriptRoot + $llvmInstallerPath)
$sevenZipPath = "C:\Program Files\7-Zip\7z.exe" $sevenZipPath = "C:\Program Files\7-Zip\7z.exe"
$specificFileInArchive = "bin\clang-format.exe" $specificFileInArchive = "bin\clang-format.exe"

View file

@ -2,6 +2,7 @@
"health": "Health - $0 Hearts", "health": "Health - $0 Hearts",
"magic": "Magic - $0", "magic": "Magic - $0",
"rupees": "Rupees - $0", "rupees": "Rupees - $0",
"keys": "Keys - $0",
"floor": "Floor $0", "floor": "Floor $0",
"basement": "Basement $0", "basement": "Basement $0",
"item_menu": "Select Item", "item_menu": "Select Item",

View file

@ -2,6 +2,7 @@
"health": "Vie - $0 Coeurs", "health": "Vie - $0 Coeurs",
"magic": "Magie - $0", "magic": "Magie - $0",
"rupees": "Rubis - $0", "rupees": "Rubis - $0",
"keys": "Clés - $0",
"floor": "Étage $0", "floor": "Étage $0",
"basement": "Sous-sol $0", "basement": "Sous-sol $0",
"item_menu": "Inventaire", "item_menu": "Inventaire",

View file

@ -2,6 +2,7 @@
"health": "Energie - $0 Herzen", "health": "Energie - $0 Herzen",
"magic": "Magie - $0", "magic": "Magie - $0",
"rupees": "Rubine - $0", "rupees": "Rubine - $0",
"keys": "Schlüssel - $0",
"floor": "Etage $0", "floor": "Etage $0",
"basement": "Keller $0", "basement": "Keller $0",
"item_menu": "Gegenstände", "item_menu": "Gegenstände",

View file

@ -44,6 +44,9 @@
"SkipText": 1, "SkipText": 1,
"TextSpeed": 5, "TextSpeed": 5,
"TimeFlowFileSelect": 1, "TimeFlowFileSelect": 1,
"TimeSavers": {
"SkipJabuJabuFish": 1
},
"TwoHandedIdle": 1, "TwoHandedIdle": 1,
"VisualAgony": 1, "VisualAgony": 1,
"WidescreenActorCulling": 1 "WidescreenActorCulling": 1

View file

@ -116,6 +116,7 @@
"Story": 1 "Story": 1
}, },
"SkipForcedDialog": 3, "SkipForcedDialog": 3,
"SkipJabuJabuFish": 1,
"SkipMiscInteractions": 1, "SkipMiscInteractions": 1,
"SkipOwlInteractions": 1, "SkipOwlInteractions": 1,
"SkipTowerEscape": 1, "SkipTowerEscape": 1,

View file

@ -1,9 +1,10 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp" #include "soh/ShipInit.hpp"
#include "z64save.h"
extern "C" SaveContext gSaveContext; extern "C" {
#include "z64save.h"
extern SaveContext gSaveContext;
}
#define CVAR_INFINITE_MAGIC_NAME CVAR_CHEAT("InfiniteMagic") #define CVAR_INFINITE_MAGIC_NAME CVAR_CHEAT("InfiniteMagic")
#define CVAR_INFINITE_MAGIC_DEFAULT 0 #define CVAR_INFINITE_MAGIC_DEFAULT 0

View file

@ -1,11 +1,12 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp" #include "soh/ShipInit.hpp"
extern "C" {
#include "functions.h" #include "functions.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
extern PlayState* gPlayState;
extern "C" PlayState* gPlayState; }
static constexpr int32_t CVAR_RUPEE_DASH_DEFAULT = 0; static constexpr int32_t CVAR_RUPEE_DASH_DEFAULT = 0;
#define CVAR_RUPEE_DASH_NAME CVAR_ENHANCEMENT("RupeeDash") #define CVAR_RUPEE_DASH_NAME CVAR_ENHANCEMENT("RupeeDash")

View file

@ -82,7 +82,7 @@ static void RollRandomTrap(uint32_t seed) {
case ADD_SPEED_TRAP: case ADD_SPEED_TRAP:
Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
GameInteractor::State::RunSpeedModifier = -2; GameInteractor::State::MovementSpeedMultiplier = 0.5f;
statusTimer = 200; statusTimer = 200;
Notification::Emit({ .message = "Speed Decreased!" }); Notification::Emit({ .message = "Speed Decreased!" });
break; break;
@ -112,7 +112,7 @@ static void RollRandomTrap(uint32_t seed) {
static void OnPlayerUpdate() { static void OnPlayerUpdate() {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (statusTimer == 0) { if (statusTimer == 0) {
GameInteractor::State::RunSpeedModifier = 0; GameInteractor::State::MovementSpeedMultiplier = 1.0f;
} }
if (eventTimer == 0) { if (eventTimer == 0) {
switch (roll) { switch (roll) {

View file

@ -4,7 +4,6 @@
#include <array> #include <array>
#include <string> #include <string>
#include <vector>
std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = { std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
{ {

View file

@ -1,12 +1,13 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp" #include "soh/ShipInit.hpp"
extern "C" {
#include "functions.h" #include "functions.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
#include "z64save.h" #include "z64save.h"
extern PlayState* gPlayState;
extern "C" PlayState* gPlayState; }
static constexpr int32_t CVAR_BGS_FIX_DEFAULT = 0; static constexpr int32_t CVAR_BGS_FIX_DEFAULT = 0;
#define CVAR_BGS_FIX_NAME CVAR_ENHANCEMENT("FixBrokenGiantsKnife") #define CVAR_BGS_FIX_NAME CVAR_ENHANCEMENT("FixBrokenGiantsKnife")

View file

@ -1,12 +1,13 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp" #include "soh/ShipInit.hpp"
extern "C" {
#include "functions.h" #include "functions.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
#include "z64save.h" #include "z64save.h"
extern PlayState* gPlayState;
extern "C" PlayState* gPlayState; }
static constexpr int32_t CVAR_NUT_UPGRADE_FIX_DEFAULT = 0; static constexpr int32_t CVAR_NUT_UPGRADE_FIX_DEFAULT = 0;
#define CVAR_NUT_UPGRADE_FIX_NAME CVAR_ENHANCEMENT("DekuNutUpgradeFix") #define CVAR_NUT_UPGRADE_FIX_NAME CVAR_ENHANCEMENT("DekuNutUpgradeFix")

View file

@ -1,10 +1,9 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp" #include "soh/ShipInit.hpp"
#include "functions.h"
#include "macros.h"
extern "C" { extern "C" {
#include "functions.h"
#include "macros.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }

View file

@ -14,7 +14,7 @@ void Ru1Init(void* actorRef) {
if (enRu1->action == 22) { if (enRu1->action == 22) {
enRu1->action = 27; enRu1->action = 27;
enRu1->drawConfig = 1; enRu1->drawConfig = 1;
enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY; enRu1->actor.flags &= ~(ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY);
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f, Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f,
Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f); Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f);
} }

View file

@ -1,15 +1,7 @@
#include "bootcommands.h" #include <stddef.h>
#include "gameconsole.h" #include <stdbool.h>
#include <macros.h>
#include <z64.h>
#include <libultraship/libultra.h>
#include <libultraship/bridge.h> #include <libultraship/bridge.h>
#include <functions.h> #include "bootcommands.h"
#include <variables.h>
#include <string.h>
#include <stdarg.h>
#include <z64.h>
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h" #include "soh/cvar_prefixes.h"
void BootCommands_Init() { void BootCommands_Init() {

View file

@ -1,7 +1,5 @@
#ifndef _BOOTCOMMANDS_H_ #ifndef _BOOTCOMMANDS_H_
#define _BOOTCOMMANDS_H_ #define _BOOTCOMMANDS_H_
#include <libultraship/libultra.h>
#include <z64.h>
void BootCommands_Init(); void BootCommands_Init();

View file

@ -1366,10 +1366,10 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
.Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming")); .Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming"));
if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) { if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) {
CVarCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson"), CVarCheckbox("Allow moving while in first-person mode", CVAR_SETTING("MoveInFirstPerson"),
CheckboxOptions() CheckboxOptions()
.Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Changes the left stick to move the player while in first person mode")); .Tooltip("Changes the left stick to move the player while in first-person mode"));
} }
CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"), CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"),
CheckboxOptions() CheckboxOptions()
@ -1432,7 +1432,9 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
CheckboxOptions() CheckboxOptions()
.Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the " .Tooltip("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the "
"controller config menu, and map the camera stick to the right stick.")); "controller config menu, and map the camera stick to the right stick.\n"
"Doesn't work in areas were the game locks the camera.\n"
"Scene reload may be necessary to enable."));
CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"), CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"),
CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Camera X Axis in:\n-Free look")); CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Camera X Axis in:\n-Free look"));
CVarCheckbox( CVarCheckbox(

View file

@ -47,6 +47,7 @@ class CustomMessage {
TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK, CustomMessage(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK,
TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
// RANDOTODO trying to declare this with capital and type causes ambiguity with the first signature
CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_ = {}, CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_ = {},
TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);

View file

@ -1130,7 +1130,7 @@ static bool SpeedModifierHandler(std::shared_ptr<Ship::Console> Console, const s
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
} }
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyRunSpeedModifier(); GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyMovementSpeedMultiplier();
try { try {
dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0] = std::stoi(args[1], nullptr, 10); dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0] = std::stoi(args[1], nullptr, 10);
@ -1471,10 +1471,7 @@ static bool AvailableChecksProcessUndiscoveredExitsHandler(std::shared_ptr<Ship:
INFO_MESSAGE("[SOH] Available Checks - Process Undiscovered Exits %s", INFO_MESSAGE("[SOH] Available Checks - Process Undiscovered Exits %s",
logic->ACProcessUndiscoveredExits ? "enabled" : "disabled"); logic->ACProcessUndiscoveredExits ? "enabled" : "disabled");
if (GameInteractor::IsSaveLoaded(true)) {
CheckTracker::RecalculateAvailableChecks(); CheckTracker::RecalculateAvailableChecks();
}
return 0; return 0;
} }

View file

@ -6,8 +6,6 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <cmath> #include <cmath>
#include <libultraship/bridge.h>
#include <libultraship/libultraship.h>
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor.h"

View file

@ -1305,6 +1305,15 @@ void DrawQuestStatusTab() {
ImGui::Text("Dungeon Items"); ImGui::Text("Dungeon Items");
static int32_t dungeonItemsScene = SCENE_DEKU_TREE; static int32_t dungeonItemsScene = SCENE_DEKU_TREE;
static int32_t lastDungeonScene = -1;
if (gPlayState != nullptr) {
int32_t sceneNum = gPlayState->sceneNum;
if (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_JABU_JABU_BOSS && lastDungeonScene != sceneNum) {
dungeonItemsScene = sceneNum;
lastDungeonScene = sceneNum;
}
}
PushStyleCombobox(THEME_COLOR); PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##DungeonSelect", SohUtils::GetSceneName(dungeonItemsScene).c_str())) { if (ImGui::BeginCombo("##DungeonSelect", SohUtils::GetSceneName(dungeonItemsScene).c_str())) {
for (int32_t dungeonIndex = SCENE_DEKU_TREE; dungeonIndex < SCENE_JABU_JABU_BOSS + 1; dungeonIndex++) { for (int32_t dungeonIndex = SCENE_DEKU_TREE; dungeonIndex < SCENE_JABU_JABU_BOSS + 1; dungeonIndex++) {

View file

@ -28,33 +28,66 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy);
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play); EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play);
const char* enemyCVarList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { const char* enemyCVarList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
CVAR_ENHANCEMENT("RandomizedEnemyList.Anubis"), CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Anubis"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"), CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"), CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"), CVAR_ENHANCEMENT("RandomizedEnemyList.Beamos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"),
CVAR_ENHANCEMENT("RandomizedEnemyList.BigSkulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.BigStalchild"), CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Biri"), CVAR_ENHANCEMENT("RandomizedEnemyList.BlackKnuckle"), CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"),
CVAR_ENHANCEMENT("RandomizedEnemyList.BlueTektite"), CVAR_ENHANCEMENT("RandomizedEnemyList.Bubble"), CVAR_ENHANCEMENT("RandomizedEnemyList.Beamos"),
CVAR_ENHANCEMENT("RandomizedEnemyList.ClubMoblin"), CVAR_ENHANCEMENT("RandomizedEnemyList.DarkLink"), CVAR_ENHANCEMENT("RandomizedEnemyList.BigSkulltula"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Dinolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Dodongo"), CVAR_ENHANCEMENT("RandomizedEnemyList.BigStalchild"),
CVAR_ENHANCEMENT("RandomizedEnemyList.FireKeese"), /*CVAR_ENHANCEMENT("RandomizedEnemyList.FlareDancer"),*/ CVAR_ENHANCEMENT("RandomizedEnemyList.Biri"),
CVAR_ENHANCEMENT("RandomizedEnemyList.FloorTile"), CVAR_ENHANCEMENT("RandomizedEnemyList.Floormaster"), CVAR_ENHANCEMENT("RandomizedEnemyList.BlackKnuckle"),
CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPeahat"), CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPot"), CVAR_ENHANCEMENT("RandomizedEnemyList.BlueTektite"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Freezard"), CVAR_ENHANCEMENT("RandomizedEnemyList.Gibdo"), CVAR_ENHANCEMENT("RandomizedEnemyList.Bubble"),
CVAR_ENHANCEMENT("RandomizedEnemyList.GohmaLarva"), CVAR_ENHANCEMENT("RandomizedEnemyList.Guay"), CVAR_ENHANCEMENT("RandomizedEnemyList.ClubMoblin"),
CVAR_ENHANCEMENT("RandomizedEnemyList.IceKeese"), CVAR_ENHANCEMENT("RandomizedEnemyList.InvisSkulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.DarkLink"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Keese"), CVAR_ENHANCEMENT("RandomizedEnemyList.LargeBaba"), CVAR_ENHANCEMENT("RandomizedEnemyList.Dinolfos"),
CVAR_ENHANCEMENT("RandomizedEnemyList.LikeLike"), CVAR_ENHANCEMENT("RandomizedEnemyList.Lizalfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Dodongo"),
CVAR_ENHANCEMENT("RandomizedEnemyList.MadScrub"), CVAR_ENHANCEMENT("RandomizedEnemyList.NormalWolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.FireKeese"),
CVAR_ENHANCEMENT("RandomizedEnemyList.PeahatLarva"), /*CVAR_ENHANCEMENT("RandomizedEnemyList.Poe"),*/ // CVAR_ENHANCEMENT("RandomizedEnemyList.FlareDancer"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Redead"), CVAR_ENHANCEMENT("RandomizedEnemyList.RedTektite"), CVAR_ENHANCEMENT("RandomizedEnemyList.FloorTile"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Shabom"), CVAR_ENHANCEMENT("RandomizedEnemyList.ShellBlade"), CVAR_ENHANCEMENT("RandomizedEnemyList.Floormaster"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Skulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.SkullKid"), CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPeahat"),
CVAR_ENHANCEMENT("RandomizedEnemyList.SmallBaba"), CVAR_ENHANCEMENT("RandomizedEnemyList.SmallStalchild"), CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPot"),
CVAR_ENHANCEMENT("RandomizedEnemyList.SpearMoblin"), CVAR_ENHANCEMENT("RandomizedEnemyList.Spike"), CVAR_ENHANCEMENT("RandomizedEnemyList.Freezard"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Stalfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Stinger"), CVAR_ENHANCEMENT("RandomizedEnemyList.Gibdo"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Tailparasan"), CVAR_ENHANCEMENT("RandomizedEnemyList.TorchSlug"), CVAR_ENHANCEMENT("RandomizedEnemyList.GohmaLarva"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Wallmaster"), CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteKnuckle"), CVAR_ENHANCEMENT("RandomizedEnemyList.Guay"),
CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteWolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"), CVAR_ENHANCEMENT("RandomizedEnemyList.IceKeese"),
CVAR_ENHANCEMENT("RandomizedEnemyList.InvisFireKeese"),
CVAR_ENHANCEMENT("RandomizedEnemyList.InvisFloormaster"),
CVAR_ENHANCEMENT("RandomizedEnemyList.InvisIceKeese"),
CVAR_ENHANCEMENT("RandomizedEnemyList.InvisKeese"),
CVAR_ENHANCEMENT("RandomizedEnemyList.InvisRedead"),
CVAR_ENHANCEMENT("RandomizedEnemyList.InvisSkulltula"),
CVAR_ENHANCEMENT("RandomizedEnemyList.InvisStalfos"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Keese"),
CVAR_ENHANCEMENT("RandomizedEnemyList.LargeBaba"),
CVAR_ENHANCEMENT("RandomizedEnemyList.LikeLike"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Lizalfos"),
CVAR_ENHANCEMENT("RandomizedEnemyList.MadScrub"),
CVAR_ENHANCEMENT("RandomizedEnemyList.NormalWolfos"),
CVAR_ENHANCEMENT("RandomizedEnemyList.PeahatLarva"),
// CVAR_ENHANCEMENT("RandomizedEnemyList.Poe"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Redead"),
CVAR_ENHANCEMENT("RandomizedEnemyList.RedTektite"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Shabom"),
CVAR_ENHANCEMENT("RandomizedEnemyList.ShellBlade"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Skulltula"),
CVAR_ENHANCEMENT("RandomizedEnemyList.SkullKid"),
CVAR_ENHANCEMENT("RandomizedEnemyList.SmallBaba"),
CVAR_ENHANCEMENT("RandomizedEnemyList.SmallStalchild"),
CVAR_ENHANCEMENT("RandomizedEnemyList.SpearMoblin"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Spike"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Stalfos"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Stinger"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Tailparasan"),
CVAR_ENHANCEMENT("RandomizedEnemyList.TorchSlug"),
CVAR_ENHANCEMENT("RandomizedEnemyList.Wallmaster"),
CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteKnuckle"),
CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteWolfos"),
CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"),
}; };
const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
@ -85,7 +118,13 @@ const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = {
"Gohma Larva", "Gohma Larva",
"Guay", "Guay",
"Ice Keese", "Ice Keese",
"Invisible Fire Keese",
"Invisible Floormaster",
"Invisible Ice Keese",
"Invisible Keese",
"Invisible Redead",
"Invisible Skulltula", "Invisible Skulltula",
"Invisible Stalfos",
"Keese", "Keese",
"Large Deku Baba", "Large Deku Baba",
"Like-Like", "Like-Like",
@ -143,11 +182,17 @@ static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] =
{ ACTOR_EN_GOMA, 7 }, // Gohma Larva (Non-Gohma rooms) { ACTOR_EN_GOMA, 7 }, // Gohma Larva (Non-Gohma rooms)
{ ACTOR_EN_CROW, 0 }, // Guay { ACTOR_EN_CROW, 0 }, // Guay
{ ACTOR_EN_FIREFLY, 4 }, // Ice Keese { ACTOR_EN_FIREFLY, 4 }, // Ice Keese
{ ACTOR_EN_FIREFLY, 0x8001 }, // Fire Keese (invisible)
{ ACTOR_EN_FLOORMAS, 0x8000 }, // Floormaster (invisible)
{ ACTOR_EN_FIREFLY, 0x8004 }, // Ice Keese (invisible)
{ ACTOR_EN_FIREFLY, 0x8002 }, // Keese (invisible)
{ ACTOR_EN_RD, 3 }, // Redead (invisible)
{ ACTOR_EN_ST, 2 }, // Skulltula (invisible) { ACTOR_EN_ST, 2 }, // Skulltula (invisible)
{ ACTOR_EN_TEST, 0 }, // Stalfos (invisible)
{ ACTOR_EN_FIREFLY, 2 }, // Regular Keese { ACTOR_EN_FIREFLY, 2 }, // Regular Keese
{ ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large) { ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large)
// Doesn't work (reliant on surface and also normally used in tandem with a leever spawner, kills itself too quickly // Doesn't work (reliant on surface, without a spawner it kills itself too quickly)
// otherwise) { ACTOR_EN_REEBA, 0 }, // Leever // { ACTOR_EN_REEBA, 0 }, // Leever
{ ACTOR_EN_RR, 0 }, // Like-Like { ACTOR_EN_RR, 0 }, // Like-Like
{ ACTOR_EN_ZF, -1 }, // Lizalfos { ACTOR_EN_ZF, -1 }, // Lizalfos
{ ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work) { ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work)

View file

@ -3,7 +3,7 @@
#include <libultraship/libultra/types.h> #include <libultraship/libultra/types.h>
#include "item-tables/ItemTableTypes.h" #include "item-tables/ItemTableTypes.h"
#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 52 #define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 58
extern const char* enemyCVarList[]; extern const char* enemyCVarList[];
extern const char* enemyNameList[]; extern const char* enemyNameList[];

View file

@ -11,6 +11,7 @@ have functions to both enable and disable said effect.
#include "GameInteractionEffect.h" #include "GameInteractionEffect.h"
#include "GameInteractor.h" #include "GameInteractor.h"
#include <libultraship/bridge.h> #include <libultraship/bridge.h>
#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
extern "C" { extern "C" {
#include <z64.h> #include <z64.h>
@ -371,19 +372,23 @@ void ForceEquipBoots::_Remove() {
GameInteractor::RawAction::ForceEquipBoots(EQUIP_VALUE_BOOTS_KOKIRI); GameInteractor::RawAction::ForceEquipBoots(EQUIP_VALUE_BOOTS_KOKIRI);
} }
// MARK: - ModifyRunSpeedModifier // MARK: - ModifyMovementSpeedMultiplier
GameInteractionEffectQueryResult ModifyRunSpeedModifier::CanBeApplied() { GameInteractionEffectQueryResult ModifyMovementSpeedMultiplier::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void ModifyRunSpeedModifier::_Apply() { void ModifyMovementSpeedMultiplier::_Apply() {
GameInteractor::State::RunSpeedModifier = parameters[0]; if (parameters[0] == -2) {
GameInteractor::State::MovementSpeedMultiplier = 0.5f;
} else if (parameters[0] == 2) {
GameInteractor::State::MovementSpeedMultiplier = 2.0f;
}
} }
void ModifyRunSpeedModifier::_Remove() { void ModifyMovementSpeedMultiplier::_Remove() {
GameInteractor::State::RunSpeedModifier = 0; GameInteractor::State::MovementSpeedMultiplier = 1.0f;
} }
// MARK: - OneHitKO // MARK: - OneHitKO
@ -485,18 +490,6 @@ void SetCollisionViewer::_Remove() {
GameInteractor::RawAction::SetCollisionViewer(false); GameInteractor::RawAction::SetCollisionViewer(false);
} }
// MARK: - SetCosmeticsColor
GameInteractionEffectQueryResult SetCosmeticsColor::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else {
return GameInteractionEffectQueryResult::Possible;
}
}
void SetCosmeticsColor::_Apply() {
GameInteractor::RawAction::SetCosmeticsColor(parameters[0], parameters[1]);
}
// MARK: - RandomizeCosmetics // MARK: - RandomizeCosmetics
GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() { GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
@ -506,7 +499,7 @@ GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() {
} }
} }
void RandomizeCosmetics::_Apply() { void RandomizeCosmetics::_Apply() {
GameInteractor::RawAction::RandomizeCosmeticsColors(true); CosmeticsEditor_RandomizeAll();
} }
// MARK: - PressButton // MARK: - PressButton

View file

@ -156,7 +156,7 @@ class ForceEquipBoots : public RemovableGameInteractionEffect, public Parameteri
void _Remove() override; void _Remove() override;
}; };
class ModifyRunSpeedModifier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ModifyMovementSpeedMultiplier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
@ -200,11 +200,6 @@ class SetCollisionViewer : public RemovableGameInteractionEffect {
void _Remove() override; void _Remove() override;
}; };
class SetCosmeticsColor : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override;
};
class RandomizeCosmetics : public GameInteractionEffectBase { class RandomizeCosmetics : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;

View file

@ -76,7 +76,7 @@ uint8_t GameInteractor_PacifistModeActive();
uint8_t GameInteractor_DisableZTargetingActive(); uint8_t GameInteractor_DisableZTargetingActive();
uint8_t GameInteractor_ReverseControlsActive(); uint8_t GameInteractor_ReverseControlsActive();
int32_t GameInteractor_DefenseModifier(); int32_t GameInteractor_DefenseModifier();
int32_t GameInteractor_RunSpeedModifier(); float GameInteractor_MovementSpeedMultiplier();
GIGravityLevel GameInteractor_GravityLevel(); GIGravityLevel GameInteractor_GravityLevel();
uint32_t GameInteractor_GetEmulatedButtons(); uint32_t GameInteractor_GetEmulatedButtons();
void GameInteractor_SetEmulatedButtons(uint32_t buttons); void GameInteractor_SetEmulatedButtons(uint32_t buttons);
@ -204,7 +204,7 @@ class GameInteractor {
static bool DisableZTargetingActive; static bool DisableZTargetingActive;
static bool ReverseControlsActive; static bool ReverseControlsActive;
static int32_t DefenseModifier; static int32_t DefenseModifier;
static int32_t RunSpeedModifier; static float MovementSpeedMultiplier;
static GIGravityLevel GravityLevel; static GIGravityLevel GravityLevel;
static uint32_t EmulatedButtons; static uint32_t EmulatedButtons;
static uint8_t RandomBombFuseTimerActive; static uint8_t RandomBombFuseTimerActive;
@ -566,8 +566,6 @@ class GameInteractor {
static void ClearAssignedButtons(uint8_t buttonSet); static void ClearAssignedButtons(uint8_t buttonSet);
static void SetTimeOfDay(uint32_t time); static void SetTimeOfDay(uint32_t time);
static void SetCollisionViewer(bool active); static void SetCollisionViewer(bool active);
static void SetCosmeticsColor(uint8_t cosmeticCategory, uint8_t colorValue);
static void RandomizeCosmeticsColors(bool excludeBiddingWarColors);
static void EmulateButtonPress(int32_t button); static void EmulateButtonPress(int32_t button);
static void AddOrTakeAmmo(int16_t amount, int16_t item); static void AddOrTakeAmmo(int16_t amount, int16_t item);
static void EmulateRandomButtonPress(uint32_t chancePercentage = 100); static void EmulateRandomButtonPress(uint32_t chancePercentage = 100);
@ -575,8 +573,10 @@ class GameInteractor {
static void SetPlayerInvincibility(bool active); static void SetPlayerInvincibility(bool active);
static void ClearCutscenePointer(); static void ClearCutscenePointer();
static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams); static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams,
static GameInteractionEffectQueryResult SpawnActor(uint32_t actorId, int32_t actorParams); std::string nameTag = "");
static GameInteractionEffectQueryResult SpawnActor(uint32_t actorId, int32_t actorParams,
std::string nameTag = "");
}; };
}; };

View file

@ -1,9 +1,9 @@
#include "GameInteractor.h" #include "GameInteractor.h"
#include <libultraship/bridge.h> #include <libultraship/bridge.h>
#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
#include "soh/Enhancements/randomizer/3drando/random.hpp" #include "soh/Enhancements/randomizer/3drando/random.hpp"
#include <math.h> #include <math.h>
#include "soh/Enhancements/debugger/colViewer.h" #include "soh/Enhancements/debugger/colViewer.h"
#include "soh/Enhancements/nametag.h"
extern "C" { extern "C" {
#include "variables.h" #include "variables.h"
@ -405,125 +405,6 @@ void GameInteractor::RawAction::SetCollisionViewer(bool active) {
} }
} }
void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint8_t colorValue) {
Color_RGBA8 newColor;
newColor.r = 255;
newColor.g = 255;
newColor.b = 255;
newColor.a = 255;
switch (colorValue) {
case GI_COLOR_RED:
newColor.r = 200;
newColor.g = 30;
newColor.b = 30;
break;
case GI_COLOR_GREEN:
newColor.r = 50;
newColor.g = 200;
newColor.b = 50;
break;
case GI_COLOR_BLUE:
newColor.r = 50;
newColor.g = 50;
newColor.b = 200;
break;
case GI_COLOR_ORANGE:
newColor.r = 200;
newColor.g = 120;
newColor.b = 0;
break;
case GI_COLOR_YELLOW:
newColor.r = 234;
newColor.g = 240;
newColor.b = 33;
break;
case GI_COLOR_PURPLE:
newColor.r = 144;
newColor.g = 13;
newColor.b = 178;
break;
case GI_COLOR_PINK:
newColor.r = 215;
newColor.g = 93;
newColor.b = 246;
break;
case GI_COLOR_BROWN:
newColor.r = 108;
newColor.g = 72;
newColor.b = 15;
break;
case GI_COLOR_BLACK:
newColor.r = 0;
newColor.g = 0;
newColor.b = 0;
break;
default:
break;
}
switch (cosmeticCategory) {
case GI_COSMETICS_TUNICS:
CVarSetColor(CVAR_COSMETIC("Link.KokiriTunic.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Link.KokiriTunic.Changed"), 1);
CVarSetColor(CVAR_COSMETIC("Link.GoronTunic.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Link.GoronTunic.Changed"), 1);
CVarSetColor(CVAR_COSMETIC("Link.ZoraTunic.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Link.ZoraTunic.Changed"), 1);
break;
case GI_COSMETICS_NAVI:
CVarSetColor(CVAR_COSMETIC("Navi.EnemyPrimary.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Navi.EnemyPrimary.Changed"), 1);
CVarSetColor(CVAR_COSMETIC("Navi.EnemySecondary.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Navi.EnemySecondary.Changed"), 1);
CVarSetColor(CVAR_COSMETIC("Navi.IdlePrimary.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Navi.IdlePrimary.Changed"), 1);
CVarSetColor(CVAR_COSMETIC("Navi.IdleSecondary.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Navi.IdleSecondary.Changed"), 1);
CVarSetColor(CVAR_COSMETIC("Navi.NPCPrimary.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Navi.NPCPrimary.Changed"), 1);
CVarSetColor(CVAR_COSMETIC("Navi.NPCSecondary.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Navi.NPCSecondary.Changed"), 1);
CVarSetColor(CVAR_COSMETIC("Navi.PropsPrimary.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Navi.PropsPrimary.Changed"), 1);
CVarSetColor(CVAR_COSMETIC("Navi.PropsSecondary.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Navi.PropsSecondary.Changed"), 1);
break;
case GI_COSMETICS_HAIR:
CVarSetColor(CVAR_COSMETIC("Link.Hair.Value"), newColor);
CVarSetInteger(CVAR_COSMETIC("Link.Hair.Changed"), 1);
break;
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
ApplyOrResetCustomGfxPatches();
}
void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) {
const char* cvarsToLock[12] = {
CVAR_COSMETIC("Link.KokiriTunic.Locked"), CVAR_COSMETIC("Link.GoronTunic.Locked"),
CVAR_COSMETIC("Link.ZoraTunic.Locked"), CVAR_COSMETIC("Navi.EnemyPrimary.Locked"),
CVAR_COSMETIC("Navi.EnemySecondary.Locked"), CVAR_COSMETIC("Navi.IdlePrimary.Locked"),
CVAR_COSMETIC("Navi.IdleSecondary.Locked"), CVAR_COSMETIC("Navi.NPCPrimary.Locked"),
CVAR_COSMETIC("Navi.NPCSecondary.Locked"), CVAR_COSMETIC("Navi.PropsPrimary.Locked"),
CVAR_COSMETIC("Navi.PropsSecondary.Locked"), CVAR_COSMETIC("Link.Hair.Locked")
};
if (excludeBiddingWarColors) {
for (uint8_t i = 0; i < 12; i++) {
CVarSetInteger(cvarsToLock[i], 1);
}
}
CosmeticsEditor_RandomizeAll();
if (excludeBiddingWarColors) {
for (uint8_t i = 0; i < 12; i++) {
CVarSetInteger(cvarsToLock[i], 0);
}
}
}
void GameInteractor::RawAction::EmulateButtonPress(int32_t button) { void GameInteractor::RawAction::EmulateButtonPress(int32_t button) {
GameInteractor::State::EmulatedButtons |= button; GameInteractor::State::EmulatedButtons |= button;
} }
@ -580,8 +461,8 @@ void GameInteractor::RawAction::ClearCutscenePointer() {
gPlayState->csCtx.segment = &null_cs; gPlayState->csCtx.segment = &null_cs;
} }
GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams,
int32_t enemyParams) { std::string nameTag) {
if (!GameInteractor::CanSpawnActor()) { if (!GameInteractor::CanSpawnActor()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@ -651,15 +532,29 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
pos.x += 10; pos.x += 10;
pos.y += 10; pos.y += 10;
pos.z += 10; pos.z += 10;
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) == Actor* actor =
NULL) { Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0);
if (actor == NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) {
NameTag_RegisterForActor(actor, nameTag.c_str());
}
if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) {
Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC);
}
} }
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} else { } else {
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) != Actor* actor =
NULL) { Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0);
if (actor != NULL) {
if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) {
NameTag_RegisterForActor(actor, nameTag.c_str());
}
if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) {
Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC);
}
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
@ -667,7 +562,8 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t actorId, int32_t actorParams) { GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t actorId, int32_t actorParams,
std::string nameTag) {
if (!GameInteractor::CanSpawnActor()) { if (!GameInteractor::CanSpawnActor()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@ -684,6 +580,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) {
NameTag_RegisterForActor((Actor*)cucco, nameTag.c_str());
}
cucco->actionFunc = func_80AB70A0_nocutscene; cucco->actionFunc = func_80AB70A0_nocutscene;
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} else if (actorId == ACTOR_EN_BOM) { } else if (actorId == ACTOR_EN_BOM) {
@ -703,8 +602,15 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} else { } else {
// Generic spawn an actor at Link's position // Generic spawn an actor at Link's position
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x, Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x,
player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actorParams, 0) != NULL) { player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actorParams, 0);
if (actor != NULL) {
if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) {
NameTag_RegisterForActor((Actor*)actor, nameTag.c_str());
}
if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) {
Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC);
}
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }

View file

@ -10,7 +10,7 @@ bool GameInteractor::State::PacifistModeActive = 0;
bool GameInteractor::State::DisableZTargetingActive = 0; bool GameInteractor::State::DisableZTargetingActive = 0;
bool GameInteractor::State::ReverseControlsActive = 0; bool GameInteractor::State::ReverseControlsActive = 0;
int32_t GameInteractor::State::DefenseModifier = 0; int32_t GameInteractor::State::DefenseModifier = 0;
int32_t GameInteractor::State::RunSpeedModifier = 0; float GameInteractor::State::MovementSpeedMultiplier = 1.0f;
GIGravityLevel GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL; GIGravityLevel GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL;
uint32_t GameInteractor::State::EmulatedButtons = 0; uint32_t GameInteractor::State::EmulatedButtons = 0;
uint8_t GameInteractor::State::RandomBombFuseTimerActive = 0; uint8_t GameInteractor::State::RandomBombFuseTimerActive = 0;
@ -81,8 +81,8 @@ int32_t GameInteractor_DefenseModifier() {
} }
// MARK: - GameInteractor::State::DisableCameraRotationActive // MARK: - GameInteractor::State::DisableCameraRotationActive
int32_t GameInteractor_RunSpeedModifier() { float GameInteractor_MovementSpeedMultiplier() {
return GameInteractor::State::RunSpeedModifier; return GameInteractor::State::MovementSpeedMultiplier;
} }
// MARK: - GameInteractor::State::DisableCameraRotationActive // MARK: - GameInteractor::State::DisableCameraRotationActive

View file

@ -1972,27 +1972,27 @@ void StaticData::HintTable_Init() {
hintTextTable[RHT_BRIDGE_OPEN_HINT] = HintText(CustomMessage("$lThe awakened ones have #already created a bridge# to the castle where the evil dwells.^", hintTextTable[RHT_BRIDGE_OPEN_HINT] = HintText(CustomMessage("$lThe awakened ones have #already created a bridge# to the castle where the evil dwells.^",
/*german*/ "$lDie Weisen haben #bereits&eine Brücke zum Portal von&Ganons Schloß gelegt#...^", /*german*/ "$lDie Weisen haben #bereits&eine Brücke zum Portal von&Ganons Schloß gelegt#...^",
/*french*/ "$lLes êtres de sagesse ont#déjà créé un pont# vers le repaire du mal.^", /*french*/ "$lLes êtres de sagesse ont#déjà créé un pont# vers le repaire du mal.^",
{QM_LBLUE})); {QM_LBLUE}, {}, TEXTBOX_TYPE_BLUE));
// /*spanish*/$lLos sabios #ya habrán creado un puente#&al castillo, de donde emana el mal.^ // /*spanish*/$lLos sabios #ya habrán creado un puente#&al castillo, de donde emana el mal.^
hintTextTable[RHT_BRIDGE_VANILLA_HINT] = HintText(CustomMessage("$6The awakened ones require the #Shadow and Spirit Medallions# as well as the #Light Arrows#.^", hintTextTable[RHT_BRIDGE_VANILLA_HINT] = HintText(CustomMessage("$6The awakened ones require the #Shadow and Spirit Medallions# as well as the #Light Arrows#.^",
/*german*/ "$6Die Weisen, die darauf warten,&daß der Held das #Amulett des Schattens, Amulett der Geister#&und die #Licht-Pfeile# sammelt.^", /*german*/ "$6Die Weisen, die darauf warten,&daß der Held das #Amulett des Schattens, Amulett der Geister#&und die #Licht-Pfeile# sammelt.^",
/*french*/ "$6Les êtres de sagesse attendront le héros muni des #Médaillons de l'Ombre et l'Esprit# et des #Flèches de Lumière#.^", /*french*/ "$6Les êtres de sagesse attendront le héros muni des #Médaillons de l'Ombre et l'Esprit# et des #Flèches de Lumière#.^",
{QM_RED, QM_YELLOW})); {QM_RED, QM_YELLOW}, {}, TEXTBOX_TYPE_BLUE));
// /*spanish*/$6Los sabios aguardarán a que el héroe obtenga tanto el #Medallón de las Sombras y el del Espíritu# junto // /*spanish*/$6Los sabios aguardarán a que el héroe obtenga tanto el #Medallón de las Sombras y el del Espíritu# junto
// a la #flecha de luz#.^ // a la #flecha de luz#.^
hintTextTable[RHT_BRIDGE_STONES_HINT] = HintText(CustomMessage("$0The awakened ones will await for the Hero to collect #[[d]] Spiritual Stone||s|#.^", hintTextTable[RHT_BRIDGE_STONES_HINT] = HintText(CustomMessage("$0The awakened ones will await for the Hero to collect #[[d]] Spiritual Stone||s|#.^",
/*german*/ "$0Die Weisen werden darauf&warten, daß der Held&#[[d]] |Heiligen Stein|Heilige Steine|# sammelt.^", /*german*/ "$0Die Weisen werden darauf&warten, daß der Held&#[[d]] |Heiligen Stein|Heilige Steine|# sammelt.^",
/*french*/ "$0Les êtres de sagesse attendront le héros muni de #[[d]] |Pierre Ancestrale|Pierres Ancestrales|#.^", /*french*/ "$0Les êtres de sagesse attendront le héros muni de #[[d]] |Pierre Ancestrale|Pierres Ancestrales|#.^",
{QM_BLUE})); {QM_BLUE}, {}, TEXTBOX_TYPE_BLUE));
// /*spanish*/$0Los sabios aguardarán a que el héroe&obtenga #[[d]] |piedra espiritual|piedras espirituales|#.^ // /*spanish*/$0Los sabios aguardarán a que el héroe&obtenga #[[d]] |piedra espiritual|piedras espirituales|#.^
hintTextTable[RHT_BRIDGE_MEDALLIONS_HINT] = HintText(CustomMessage("$8The awakened ones will await for the Hero to collect #[[d]] Medallion||s|#.^", hintTextTable[RHT_BRIDGE_MEDALLIONS_HINT] = HintText(CustomMessage("$8The awakened ones will await for the Hero to collect #[[d]] Medallion||s|#.^",
/*german*/ "$8Die Weisen werden darauf&warten, daß der Held&#[[d]] Amulett||e|# sammelt.^", /*german*/ "$8Die Weisen werden darauf&warten, daß der Held&#[[d]] Amulett||e|# sammelt.^",
/*french*/ "$8Les êtres de sagesse attendront le héros muni de #[[d]] Médaillon||s|#.^", /*french*/ "$8Les êtres de sagesse attendront le héros muni de #[[d]] Médaillon||s|#.^",
{QM_RED})); {QM_RED}, {}, TEXTBOX_TYPE_BLUE));
// /*spanish*/$8Los sabios aguardarán a que el héroe&obtenga #[[d]] |medallón|medallones|#.^ // /*spanish*/$8Los sabios aguardarán a que el héroe&obtenga #[[d]] |medallón|medallones|#.^
hintTextTable[RHT_BRIDGE_REWARDS_HINT] = HintText(CustomMessage("$CThe awakened ones will await for the Hero to collect #[[d]]# |#Spiritual Stone# or #Medallion#|" hintTextTable[RHT_BRIDGE_REWARDS_HINT] = HintText(CustomMessage("$CThe awakened ones will await for the Hero to collect #[[d]]# |#Spiritual Stone# or #Medallion#|"
@ -2001,26 +2001,26 @@ void StaticData::HintTable_Init() {
"#Heilige Steine# oder #Amulette#| sammelt.^", "#Heilige Steine# oder #Amulette#| sammelt.^",
/*french*/ "$CLes êtres de sagesse attendront le héros muni de #[[d]]# |#Pierre Ancestrale# ou #Médaillon#" /*french*/ "$CLes êtres de sagesse attendront le héros muni de #[[d]]# |#Pierre Ancestrale# ou #Médaillon#"
"|#Pierres Ancestrales# ou #Médaillons#|.^", "|#Pierres Ancestrales# ou #Médaillons#|.^",
{QM_YELLOW, QM_BLUE, QM_RED})); {QM_YELLOW, QM_BLUE, QM_RED}, {}, TEXTBOX_TYPE_BLUE));
// /*spanish*/$CLos sabios aguardarán a que el héroe obtenga #[[d]]# |#piedra espiritual# o #medallón#| // /*spanish*/$CLos sabios aguardarán a que el héroe obtenga #[[d]]# |#piedra espiritual# o #medallón#|
//#piedras espirtuales# y #medallones#|.^ //#piedras espirtuales# y #medallones#|.^
hintTextTable[RHT_BRIDGE_DUNGEONS_HINT] = HintText(CustomMessage("$mThe awakened ones will await for the Hero to conquer #[[d]] Dungeon||s|#.^", hintTextTable[RHT_BRIDGE_DUNGEONS_HINT] = HintText(CustomMessage("$mThe awakened ones will await for the Hero to conquer #[[d]] Dungeon||s|#.^",
/*german*/ "$mDie Weisen werden darauf&warten, daß der Held&#[[d]] Labyrinth||e|# abschließt.^", /*german*/ "$mDie Weisen werden darauf&warten, daß der Held&#[[d]] Labyrinth||e|# abschließt.^",
/*french*/ "$mLes êtres de sagesse attendront la conquête de #[[d]] Donjon||s|#.^", /*french*/ "$mLes êtres de sagesse attendront la conquête de #[[d]] Donjon||s|#.^",
{QM_PINK})); {QM_PINK}, {}, TEXTBOX_TYPE_BLUE));
// /*spanish*/$mLos sabios aguardarán a que el héroe complete #[[d]] mazmorra||s|#.^ // /*spanish*/$mLos sabios aguardarán a que el héroe complete #[[d]] mazmorra||s|#.^
hintTextTable[RHT_BRIDGE_TOKENS_HINT] = HintText(CustomMessage("$sThe awakened ones will await for the Hero to collect #[[d]] Gold Skulltula Token||s|#.^", hintTextTable[RHT_BRIDGE_TOKENS_HINT] = HintText(CustomMessage("$sThe awakened ones will await for the Hero to collect #[[d]] Gold Skulltula Token||s|#.^",
/*german*/ "$sDie Weisen werden darauf&warten, daß der Held&#[[d]] Skulltula-Symbol||e|# sammelt.^", /*german*/ "$sDie Weisen werden darauf&warten, daß der Held&#[[d]] Skulltula-Symbol||e|# sammelt.^",
/*french*/ "$sLes êtres de sagesse attendront le héros muni de #[[d]] Symbole||s| de Skulltula d'or#.^", /*french*/ "$sLes êtres de sagesse attendront le héros muni de #[[d]] Symbole||s| de Skulltula d'or#.^",
{QM_YELLOW})); {QM_YELLOW}, {}, TEXTBOX_TYPE_BLUE));
// /*spanish*/$sLos sabios aguardarán a que el héroe obtenga #[[d]] símbolo||s| de skulltula dorada#.^ // /*spanish*/$sLos sabios aguardarán a que el héroe obtenga #[[d]] símbolo||s| de skulltula dorada#.^
hintTextTable[RHT_BRIDGE_GREG_HINT] = HintText(CustomMessage("$gThe awakened ones will await for the Hero to find #Greg#.^", hintTextTable[RHT_BRIDGE_GREG_HINT] = HintText(CustomMessage("$gThe awakened ones will await for the Hero to find #Greg#.^",
/*german*/ "$gDie Weisen werden darauf&warten, daß der Held&#Greg# findet.^", /*german*/ "$gDie Weisen werden darauf&warten, daß der Held&#Greg# findet.^",
/*french*/ "$gLes êtres de sagesse attendront le héros muni de #Greg#.^", /*french*/ "$gLes êtres de sagesse attendront le héros muni de #Greg#.^",
{QM_GREEN})); {QM_GREEN}, {}, TEXTBOX_TYPE_BLUE));
/*-------------------------- /*--------------------------
@ -2174,22 +2174,22 @@ void StaticData::HintTable_Init() {
hintTextTable[RHT_CHILD_ALTAR_STONES] = HintText(CustomMessage("3 Spiritual Stones found in Hyrule...^$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^", hintTextTable[RHT_CHILD_ALTAR_STONES] = HintText(CustomMessage("3 Spiritual Stones found in Hyrule...^$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^",
/*german*/ "Drei Heilige Steine, zu finden in Hyrule...^$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^", /*german*/ "Drei Heilige Steine, zu finden in Hyrule...^$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^",
/*french*/ "Les trois Pierres Ancestrales cachées&dans Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^", /*french*/ "Les trois Pierres Ancestrales cachées&dans Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^",
{QM_GREEN, QM_RED, QM_BLUE}, {true, true, true})); {QM_GREEN, QM_RED, QM_BLUE}, {true, true, true}, TEXTBOX_TYPE_BLUE));
// /*spanish*/ Tres piedras espirituales halladas por Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^ // /*spanish*/ Tres piedras espirituales halladas por Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^
hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN] = HintText(CustomMessage("$oYe who may become a Hero...&The path to the future is open...", hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN] = HintText(CustomMessage("$oYe who may become a Hero...&The path to the future is open...",
/*german*/ "$oJener auf dem Weg des Helden...&Der Pfad zur Zukunft sei geöffnet...", /*german*/ "$oJener auf dem Weg des Helden...&Der Pfad zur Zukunft sei geöffnet...",
/*french*/ "$oÀ celui qui a quête de devenir&héros...&Le futur vous accueille béant...")); /*french*/ "$oÀ celui qui a quête de devenir&héros...&Le futur vous accueille béant...", TEXTBOX_TYPE_BLUE));
// /*spanish*/$oPara aquel que se convierta en el héroe...&La puerta al futuro está a su disposición... // /*spanish*/$oPara aquel que se convierta en el héroe...&La puerta al futuro está a su disposición...
hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY] = HintText(CustomMessage("$cYe who may become a Hero...&Stand with the Ocarina and&play the Song of Time.", hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY] = HintText(CustomMessage("$cYe who may become a Hero...&Stand with the Ocarina and&play the Song of Time.",
/*german*/ "$cJener auf dem Weg des Helden...&Nehme er seine Okarina zur Hand und spiele hier die Hymne der Zeit.", /*german*/ "$cJener auf dem Weg des Helden...&Nehme er seine Okarina zur Hand und spiele hier die Hymne der Zeit.",
/*french*/ "$cÀ celui qui a quête de devenir&héros...&Portez l'Ocarina et jouez&le chant du temps.")); /*french*/ "$cÀ celui qui a quête de devenir&héros...&Portez l'Ocarina et jouez&le chant du temps.", TEXTBOX_TYPE_BLUE));
// /*spanish*/$cPara aquel que se convierta en el héroe...&Tome la ocarina y&entone la Canción del Tiempo. // /*spanish*/$cPara aquel que se convierta en el héroe...&Tome la ocarina y&entone la Canción del Tiempo.
hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED] = HintText(CustomMessage("$iYe who may become a Hero...&Offer the spiritual stones and&play the Song of Time.", hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED] = HintText(CustomMessage("$iYe who may become a Hero...&Offer the spiritual stones and&play the Song of Time.",
/*german*/ "$iJener mit den drei Heiligen Steinen nehme er seine Okarina zur Hand und spiele hier die Hymne der Zeit.", /*german*/ "$iJener mit den drei Heiligen Steinen nehme er seine Okarina zur Hand und spiele hier die Hymne der Zeit.",
/*french*/ "$iÀ celui qui a quête de devenir&héros... Présentez les Pierres&Ancestrales et jouez&le chant du temps.")); /*french*/ "$iÀ celui qui a quête de devenir&héros... Présentez les Pierres&Ancestrales et jouez&le chant du temps.", TEXTBOX_TYPE_BLUE));
// /*spanish*/$iPara aquel que se convierta en el héroe...&Tome las piedras espirituales y&entone la Canción del Tiempo. // /*spanish*/$iPara aquel que se convierta en el héroe...&Tome las piedras espirituales y&entone la Canción del Tiempo.
hintTextTable[RHT_ADULT_ALTAR_MEDALLIONS] = HintText(CustomMessage("An awakening voice from the Sacred Realm will call those destined to be Sages, who dwell in the #five temples#.^" hintTextTable[RHT_ADULT_ALTAR_MEDALLIONS] = HintText(CustomMessage("An awakening voice from the Sacred Realm will call those destined to be Sages, who dwell in the #five temples#.^"

View file

@ -313,11 +313,11 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
/*german*/ "Man erzählt sich, daß ein #Tauchexperiment# #[[1]]# einbrächte.", /*german*/ "Man erzählt sich, daß ein #Tauchexperiment# #[[1]]# einbrächte.",
/*french*/ "Selon moi, l'#expérience de plongée# donne #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, l'#expérience de plongée# donne #[[1]]#.", {QM_RED, QM_GREEN}));
// /*spanish*/ Según dicen, #bucear para un experimento# se premia con #[[1]]#. // /*spanish*/ Según dicen, #bucear para un experimento# se premia con #[[1]]#.
// RANDOTODO: needs translation
hintTextTable[RHT_ZD_FISH] = HintText(CustomMessage("They say that a #fish by a waterfall# hoards #[[1]]#.", hintTextTable[RHT_ZD_FISH] = HintText(CustomMessage("They say that a #fish by a waterfall# hoards #[[1]]#.",
/*german*/ "Man erzählt sich, daß ein #Fisch nahe eines Wasserfalls# #[[1]]# horte.", /*german*/ "Man erzählt sich, daß ein #Fisch nahe eines Wasserfalls# #[[1]]# horte.",
/*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, un #poisson près d'une cascade# a #[[1]]#.", {QM_RED, QM_GREEN}));
// /*spanish*/ Según dicen, #[[1]]#. // /*spanish*/ Según dicen, un #pez junto a una cascada# otorga #[[1]]#.
hintTextTable[RHT_GC_ROLLING_GORON_AS_ADULT] = HintText(CustomMessage("They say that #reassuring a young Goron# is rewarded with #[[1]]#.", hintTextTable[RHT_GC_ROLLING_GORON_AS_ADULT] = HintText(CustomMessage("They say that #reassuring a young Goron# is rewarded with #[[1]]#.",
@ -1492,9 +1492,17 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
/*french*/ "Selon moi, une #rucheau derrière le Roi des Zoras# cache #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, une #rucheau derrière le Roi des Zoras# cache #[[1]]#.", {QM_RED, QM_GREEN}));
// /*spanish*/ Según dicen, una #colmena detrás del rey de los zoras# esconde #[[1]]#. // /*spanish*/ Según dicen, una #colmena detrás del rey de los zoras# esconde #[[1]]#.
hintTextTable[RHT_POT_KOKIRI_FOREST] = HintText(CustomMessage("They say that a #pot in Kokiri Forest# contains #[[1]]#.", hintTextTable[RHT_POT_LINKS_HOUSE] = HintText(CustomMessage("They say that the #pot in the hero's house# contains #[[1]]#.",
/*german*/ "Man erzählt sich, daß ein #Krug im Kokiri-Wald# #[[1]]# enthielte.", /*german*/ "Man erzählt sich, daß eine #Vase im Kokiri-Wald# #[[1]]# enthielte.", //TODO_TRANSLATE update to match
/*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); //TODO_TRANSLATE update to match
hintTextTable[RHT_POT_TWINS_HOUSE] = HintText(CustomMessage("They say that a #pot shared by twins# contains #[[1]]#.",
/*german*/ "Man erzählt sich, daß eine #Vase im Kokiri-Wald# #[[1]]# enthielte.", //TODO_TRANSLATE update to match
/*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); //TODO_TRANSLATE update to match
hintTextTable[RHT_POT_KNOW_IT_ALL] = HintText(CustomMessage("They say that a #know-it-all bother's pot# contains #[[1]]#.",
/*german*/ "Man erzählt sich, daß eine #Vase im Kokiri-Wald# #[[1]]# enthielte.", //TODO_TRANSLATE update to match
/*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); //TODO_TRANSLATE update to match
hintTextTable[RHT_TH_BREAK_ROOM_FRONT_POT] = HintText(CustomMessage("They say that the #front pot watched by resting thieves# contains #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE hintTextTable[RHT_TH_BREAK_ROOM_FRONT_POT] = HintText(CustomMessage("They say that the #front pot watched by resting thieves# contains #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE
@ -1532,15 +1540,24 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
/*german*/ "Man erzählt sich, daß ein #Krug in der Gespensterwüste# #[[1]]# enthielte.", /*german*/ "Man erzählt sich, daß ein #Krug in der Gespensterwüste# #[[1]]# enthielte.",
/*french*/ "Selon moi, une #jarre dans le Désert Hanté# contient #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, une #jarre dans le Désert Hanté# contient #[[1]]#.", {QM_RED, QM_GREEN}));
hintTextTable[RHT_POT_MARKET] = HintText(CustomMessage("They say that a #pot in Market# contains #[[1]]#.", hintTextTable[RHT_POT_GUARD_HOUSE] = HintText(CustomMessage("They say that a #pot in the Guard House# contains #[[1]]#.",
/*german*/ "Man erzählt sich, daß ein #Krug auf dem Markt# #[[1]]# enthielte.", /*german*/ "Man erzählt sich, daß eine #Krug auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match
/*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match
hintTextTable[RHT_POT_POE_SHOP] = HintText(CustomMessage("They say that a #pot in the Poe Shop# contains #[[1]]#.",
/*german*/ "Man erzählt sich, daß eine #Krug auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match
/*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match
hintTextTable[RHT_POT_ALLEY_HOUSE] = HintText(CustomMessage("They say that a #bearded man's pot# contains #[[1]]#.",
/*german*/ "Man erzählt sich, daß eine #Krug auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match
/*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match
hintTextTable[RHT_POT_KAKARIKO] = HintText(CustomMessage("They say that a #pot in Kakariko Village# contains #[[1]]#.", hintTextTable[RHT_POT_KAKARIKO] = HintText(CustomMessage("They say that a #pot in Kakariko Village# contains #[[1]]#.",
/*german*/ "Man erzählt sich, daß ein #Krug in Kakariko# #[[1]]# enthielte.", /*german*/ "Man erzählt sich, daß ein #Krug in Kakariko# #[[1]]# enthielte.",
/*french*/ "Selon moi, une #jarre dans le Village de Cocorico# contient #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, une #jarre dans le Village de Cocorico# contient #[[1]]#.", {QM_RED, QM_GREEN}));
hintTextTable[RHT_POT_GRAVEYARD] = HintText(CustomMessage("They say that a #pot in Graveyard# contains #[[1]]#.", hintTextTable[RHT_POT_DAMPE] = HintText(CustomMessage("They say that a #pot in gravekeeper's tomb# contains #[[1]]#.",
//TODO_TRANSLATE check these to make sure they refernce dampe's tomb not the graveyard area
/*german*/ "Man erzählt sich, daß ein #Krug auf dem Friedhof# #[[1]]# enthielte.", /*german*/ "Man erzählt sich, daß ein #Krug auf dem Friedhof# #[[1]]# enthielte.",
/*french*/ "Selon moi, une #jarre dans le Cimetière# contient #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, une #jarre dans le Cimetière# contient #[[1]]#.", {QM_RED, QM_GREEN}));
@ -1564,13 +1581,17 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
/*german*/ "Man erzählt sich, daß ein #Krug auf der Lon Lon-Farm# #[[1]]# enthielte.", /*german*/ "Man erzählt sich, daß ein #Krug auf der Lon Lon-Farm# #[[1]]# enthielte.",
/*french*/ "Selon moi, une #jarre dans le Ranch Lon Lon# contient #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, une #jarre dans le Ranch Lon Lon# contient #[[1]]#.", {QM_RED, QM_GREEN}));
hintTextTable[RHT_POT_HYRULE_FIELD] = HintText(CustomMessage("They say that a #pot in Hyrule Field# contains #[[1]]#.", hintTextTable[RHT_POT_TALONS_HOUSE] = HintText(CustomMessage("They say that a #pot in Talon's Bedroom# contains #[[1]]#.",
/*german*/ "Man erzählt sich, daß ein #Krug in der Hylianischen Steppe# #[[1]]# enthielte.", /*german*/ "Man erzählt sich, daß eine #Krug auf der Lon Lon-Farm# #[[1]]# enthielte.",//TODO_TRANSLATE update to match
/*french*/ "Selon moi, une #jarre dans la Plaine d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, une #jarre dans le Ranch Lon Lon# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match
hintTextTable[RHT_POT_HYRULE_CASTLE] = HintText(CustomMessage("They say that a #pot in Hyrule Castle# contains #[[1]]#.", hintTextTable[RHT_POT_WEB_GROTTO] = HintText(CustomMessage("They say that a #pot behind a grotto's webbing# contains #[[1]]#.",
/*german*/ "Man erzählt sich, daß ein #Krug in Schloß Hyrule# #[[1]]# enthielte.", /*german*/ "Man erzählt sich, daß eine #Krug in der Hylianischen Steppe# #[[1]]# enthielte.",//TODO_TRANSLATE update to match
/*french*/ "Selon moi, une #jarre dans le Château d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN})); /*french*/ "Selon moi, une #jarre dans la Plaine d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match
hintTextTable[RHT_POT_MUD_WALL_GROTTO] = HintText(CustomMessage("They say that a #pot walled off in a grotto# contains #[[1]]#.",
/*german*/ "Man erzählt sich, daß eine #Krug in Schloß Hyrule# #[[1]]# enthielte.",//TODO_TRANSLATE update to match
/*french*/ "Selon moi, une #jarre dans le Château d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match
hintTextTable[RHT_KOKIRI_FOREST_RUPEE] = HintText(CustomMessage("They say that a rupee in a #tranquil forest# hides #[[1]]#.", hintTextTable[RHT_KOKIRI_FOREST_RUPEE] = HintText(CustomMessage("They say that a rupee in a #tranquil forest# hides #[[1]]#.",
/*german*/ "Man erzählt sich, daß ein Rubin in einem #ruhigen Wald# #[[1]]# verstecke.", /*german*/ "Man erzählt sich, daß ein Rubin in einem #ruhigen Wald# #[[1]]# verstecke.",

View file

@ -734,22 +734,24 @@ std::vector<RandomizerCheck> FindItemsAndMarkHinted(std::vector<RandomizerGet> i
void CreateChildAltarHint() { void CreateChildAltarHint() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled() && ctx->GetOption(RSK_TOT_ALTAR_HINT)) { if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled()) {
std::vector<RandomizerCheck> stoneLocs = {}; std::vector<RandomizerCheck> stoneLocs = {};
std::vector<RandomizerArea> stoneAreas = {};
if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) {
// force marking the rewards as hinted if they are at the end of dungeons as they can be inferred // force marking the rewards as hinted if they are at the end of dungeons as they can be inferred
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) ||
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) {
stoneLocs = FindItemsAndMarkHinted({ RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE }, {}); stoneLocs = FindItemsAndMarkHinted({ RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE }, {});
} else { } else {
stoneLocs = stoneLocs = FindItemsAndMarkHinted({ RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE },
FindItemsAndMarkHinted({ RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE }, { RC_ALTAR_HINT_CHILD }); { RC_ALTAR_HINT_CHILD });
} }
std::vector<RandomizerArea> stoneAreas = {};
for (auto loc : stoneLocs) { for (auto loc : stoneLocs) {
if (loc != RC_UNKNOWN_CHECK) { if (loc != RC_UNKNOWN_CHECK) {
stoneAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); stoneAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea());
} }
} }
}
ctx->AddHint(RH_ALTAR_CHILD, Hint(RH_ALTAR_CHILD, HINT_TYPE_ALTAR_CHILD, {}, stoneLocs, stoneAreas)); ctx->AddHint(RH_ALTAR_CHILD, Hint(RH_ALTAR_CHILD, HINT_TYPE_ALTAR_CHILD, {}, stoneLocs, stoneAreas));
} }
} }
@ -758,6 +760,7 @@ void CreateAdultAltarHint() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
if (!ctx->GetHint(RH_ALTAR_ADULT)->IsEnabled()) { if (!ctx->GetHint(RH_ALTAR_ADULT)->IsEnabled()) {
std::vector<RandomizerCheck> medallionLocs = {}; std::vector<RandomizerCheck> medallionLocs = {};
std::vector<RandomizerArea> medallionAreas = {};
if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) {
// force marking the rewards as hinted if they are at the end of dungeons as they can be inferred // force marking the rewards as hinted if they are at the end of dungeons as they can be inferred
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) ||
@ -770,13 +773,12 @@ void CreateAdultAltarHint() {
RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION }, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION },
{ RC_ALTAR_HINT_ADULT }); { RC_ALTAR_HINT_ADULT });
} }
}
std::vector<RandomizerArea> medallionAreas = {};
for (auto loc : medallionLocs) { for (auto loc : medallionLocs) {
if (loc != RC_UNKNOWN_CHECK) { if (loc != RC_UNKNOWN_CHECK) {
medallionAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); medallionAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea());
} }
} }
}
ctx->AddHint(RH_ALTAR_ADULT, Hint(RH_ALTAR_ADULT, HINT_TYPE_ALTAR_ADULT, {}, medallionLocs, medallionAreas)); ctx->AddHint(RH_ALTAR_ADULT, Hint(RH_ALTAR_ADULT, HINT_TYPE_ALTAR_ADULT, {}, medallionLocs, medallionAreas));
} }
} }

View file

@ -354,7 +354,7 @@ void PlaceJunkInExcludedLocation(const RandomizerCheck il) {
// place a non-advancement item in this location // place a non-advancement item in this location
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
for (size_t i = 0; i < ItemPool.size(); i++) { for (size_t i = 0; i < ItemPool.size(); i++) {
if (!Rando::StaticData::RetrieveItem(ItemPool[i]).IsAdvancement()) { if (Rando::StaticData::RetrieveItem(ItemPool[i]).GetCategory() == ITEM_CATEGORY_JUNK) {
ctx->PlaceItemInLocation(il, ItemPool[i]); ctx->PlaceItemInLocation(il, ItemPool[i]);
ItemPool.erase(ItemPool.begin() + i); ItemPool.erase(ItemPool.begin() + i);
return; return;

View file

@ -109,11 +109,11 @@ void Rando::StaticData::RegisterPotLocations() {
// clang-format off // clang-format off
// Overworld Pots // Overworld Pots
// Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Hint Text Key Vanilla Spoiler Collection Check // Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Hint Text Key Vanilla Spoiler Collection Check
locationTable[RC_KF_LINKS_HOUSE_POT] = Location::Pot(RC_KF_LINKS_HOUSE_POT, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_LINKS_HOUSE, TWO_ACTOR_PARAMS(-118, 51), "Links House Pot", RHT_POT_KOKIRI_FOREST, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_LINKS_HOUSE_POT)); locationTable[RC_KF_LINKS_HOUSE_POT] = Location::Pot(RC_KF_LINKS_HOUSE_POT, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_LINKS_HOUSE, TWO_ACTOR_PARAMS(-118, 51), "Links House Pot", RHT_POT_LINKS_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_LINKS_HOUSE_POT));
locationTable[RC_KF_TWINS_HOUSE_POT_2] = Location::Pot(RC_KF_TWINS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(35, 57), "Twins House Pot 2", RHT_POT_KOKIRI_FOREST, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_2)); locationTable[RC_KF_TWINS_HOUSE_POT_2] = Location::Pot(RC_KF_TWINS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(35, 57), "Twins House Pot 2", RHT_POT_TWINS_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_2));
locationTable[RC_KF_TWINS_HOUSE_POT_1] = Location::Pot(RC_KF_TWINS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(33, -55), "Twins House Pot 1", RHT_POT_KOKIRI_FOREST, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_1)); locationTable[RC_KF_TWINS_HOUSE_POT_1] = Location::Pot(RC_KF_TWINS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(33, -55), "Twins House Pot 1", RHT_POT_TWINS_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_1));
locationTable[RC_KF_BROTHERS_HOUSE_POT_1] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-134, -29), "Brothers House Pot 1", RHT_POT_KOKIRI_FOREST, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_1)); locationTable[RC_KF_BROTHERS_HOUSE_POT_1] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-134, -29), "Brothers House Pot 1", RHT_POT_KNOW_IT_ALL, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_1));
locationTable[RC_KF_BROTHERS_HOUSE_POT_2] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-68, 114), "Brothers House Pot 2", RHT_POT_KOKIRI_FOREST, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_2)); locationTable[RC_KF_BROTHERS_HOUSE_POT_2] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-68, 114), "Brothers House Pot 2", RHT_POT_KNOW_IT_ALL, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_2));
locationTable[RC_TH_BREAK_ROOM_FRONT_POT] = Location::Pot(RC_TH_BREAK_ROOM_FRONT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1438, -3629), "Break Room Front Pot", RHT_TH_BREAK_ROOM_FRONT_POT, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_BREAK_ROOM_FRONT_POT)); locationTable[RC_TH_BREAK_ROOM_FRONT_POT] = Location::Pot(RC_TH_BREAK_ROOM_FRONT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1438, -3629), "Break Room Front Pot", RHT_TH_BREAK_ROOM_FRONT_POT, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_BREAK_ROOM_FRONT_POT));
locationTable[RC_TH_BREAK_ROOM_BACK_POT] = Location::Pot(RC_TH_BREAK_ROOM_BACK_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1403, -3679), "Break Room Back Pot", RHT_TH_BREAK_ROOM_BACK_POT, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_BREAK_ROOM_BACK_POT)); locationTable[RC_TH_BREAK_ROOM_BACK_POT] = Location::Pot(RC_TH_BREAK_ROOM_BACK_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1403, -3679), "Break Room Back Pot", RHT_TH_BREAK_ROOM_BACK_POT, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_BREAK_ROOM_BACK_POT));
locationTable[RC_TH_KITCHEN_POT_1] = Location::Pot(RC_TH_KITCHEN_POT_1, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1908, -789), "Kitchen Pot 1", RHT_TH_KITCHEN_POT_1, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_KITCHEN_POT_1)); locationTable[RC_TH_KITCHEN_POT_1] = Location::Pot(RC_TH_KITCHEN_POT_1, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1908, -789), "Kitchen Pot 1", RHT_TH_KITCHEN_POT_1, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_KITCHEN_POT_1));
@ -134,64 +134,64 @@ void Rando::StaticData::RegisterPotLocations() {
locationTable[RC_WASTELAND_NEAR_GS_POT_2] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_2, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(485, -2463), "Near GS Pot 2", RHT_POT_WASTELAND, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_2)); locationTable[RC_WASTELAND_NEAR_GS_POT_2] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_2, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(485, -2463), "Near GS Pot 2", RHT_POT_WASTELAND, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_2));
locationTable[RC_WASTELAND_NEAR_GS_POT_3] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_3, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(806, -2426), "Near GS Pot 3", RHT_POT_WASTELAND, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_3)); locationTable[RC_WASTELAND_NEAR_GS_POT_3] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_3, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(806, -2426), "Near GS Pot 3", RHT_POT_WASTELAND, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_3));
locationTable[RC_WASTELAND_NEAR_GS_POT_4] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_4, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(801, -2460), "Near GS Pot 4", RHT_POT_WASTELAND, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_4)); locationTable[RC_WASTELAND_NEAR_GS_POT_4] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_4, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(801, -2460), "Near GS Pot 4", RHT_POT_WASTELAND, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_4));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-60, 27), "Guard House Child Pot 1", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_1)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-60, 27), "Guard House Child Pot 1", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_1));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-89, 28), "Guard House Child Pot 2", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_2)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-89, 28), "Guard House Child Pot 2", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_2));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-110, 6), "Guard House Child Pot 3", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_3)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-110, 6), "Guard House Child Pot 3", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_3));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-58, -7), "Guard House Child Pot 4", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_4)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-58, -7), "Guard House Child Pot 4", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_4));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-80, -7), "Guard House Child Pot 5", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_5)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-80, -7), "Guard House Child Pot 5", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_5));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-65, -45), "Guard House Child Pot 6", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_6)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-65, -45), "Guard House Child Pot 6", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_6));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-85, -41), "Guard House Child Pot 7", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_7)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-85, -41), "Guard House Child Pot 7", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_7));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-107, -45), "Guard House Child Pot 8", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_8)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-107, -45), "Guard House Child Pot 8", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_8));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-66, -79), "Guard House Child Pot 9", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_9)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-66, -79), "Guard House Child Pot 9", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_9));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-88, -84), "Guard House Child Pot 10", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_10)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-88, -84), "Guard House Child Pot 10", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_10));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, 215), "Guard House Child Pot 11", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_11)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, 215), "Guard House Child Pot 11", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_11));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_12] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_12, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 148), "Guard House Child Pot 12", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_12)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_12] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_12, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 148), "Guard House Child Pot 12", RHT_POT_GUARD_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_12));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_13] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_13, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(73, 117), "Guard House Child Pot 13", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_13)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_13] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_13, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(73, 117), "Guard House Child Pot 13", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_13));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_14] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_14, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 123), "Guard House Child Pot 14", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_14)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_14] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_14, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 123), "Guard House Child Pot 14", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_14));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_15] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_15, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(43, 89), "Guard House Child Pot 15", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_15)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_15] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_15, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(43, 89), "Guard House Child Pot 15", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_15));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_16] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_16, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 81), "Guard House Child Pot 16", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_16)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_16] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_16, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 81), "Guard House Child Pot 16", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_16));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_17] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_17, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(21, 73), "Guard House Child Pot 17", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_17)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_17] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_17, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(21, 73), "Guard House Child Pot 17", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_17));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_18] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_18, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(64, 45), "Guard House Child Pot 18", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_18)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_18] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_18, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(64, 45), "Guard House Child Pot 18", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_18));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_19] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_19, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(84, 31), "Guard House Child Pot 19", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_19)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_19] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_19, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(84, 31), "Guard House Child Pot 19", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_19));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_20] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_20, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, 26), "Guard House Child Pot 20", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_20)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_20] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_20, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, 26), "Guard House Child Pot 20", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_20));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_21] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_21, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(20, 34), "Guard House Child Pot 21", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_21)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_21] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_21, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(20, 34), "Guard House Child Pot 21", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_21));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_22] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_22, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(89, -2), "Guard House Child Pot 22", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_22)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_22] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_22, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(89, -2), "Guard House Child Pot 22", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_22));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_23] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_23, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -12), "Guard House Child Pot 23", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_23)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_23] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_23, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -12), "Guard House Child Pot 23", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_23));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_24] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_24, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, -5), "Guard House Child Pot 24", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_24)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_24] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_24, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, -5), "Guard House Child Pot 24", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_24));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_25] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_25, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(16, -6), "Guard House Child Pot 25", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_25)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_25] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_25, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(16, -6), "Guard House Child Pot 25", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_25));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_26] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_26, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, -44), "Guard House Child Pot 26", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_26)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_26] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_26, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, -44), "Guard House Child Pot 26", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_26));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_27] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_27, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(37, -40), "Guard House Child Pot 27", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_27)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_27] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_27, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(37, -40), "Guard House Child Pot 27", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_27));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_28] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_28, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -80), "Guard House Child Pot 28", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_28)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_28] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_28, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -80), "Guard House Child Pot 28", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_28));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_29] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_29, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(50, -74), "Guard House Child Pot 29", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_29)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_29] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_29, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(50, -74), "Guard House Child Pot 29", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_29));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_30] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_30, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(28, -79), "Guard House Child Pot 30", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_30)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_30] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_30, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(28, -79), "Guard House Child Pot 30", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_30));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_31] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_31, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(39, -111), "Guard House Child Pot 31", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_31)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_31] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_31, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(39, -111), "Guard House Child Pot 31", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_31));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_32] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_32, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(169, 216), "Guard House Child Pot 32", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_32)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_32] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_32, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(169, 216), "Guard House Child Pot 32", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_32));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_33] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_33, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 166), "Guard House Child Pot 33", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_33)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_33] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_33, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 166), "Guard House Child Pot 33", RHT_POT_GUARD_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_33));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_34] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_34, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, 120), "Guard House Child Pot 34", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_34)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_34] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_34, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, 120), "Guard House Child Pot 34", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_34));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_35] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_35, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(177, 85), "Guard House Child Pot 35", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_35)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_35] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_35, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(177, 85), "Guard House Child Pot 35", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_35));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_36] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_36, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(155, 39), "Guard House Child Pot 36", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_36)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_36] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_36, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(155, 39), "Guard House Child Pot 36", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_36));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_37] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_37, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(184, 13), "Guard House Child Pot 37", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_37)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_37] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_37, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(184, 13), "Guard House Child Pot 37", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_37));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_38] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_38, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -1), "Guard House Child Pot 38", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_38)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_38] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_38, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -1), "Guard House Child Pot 38", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_38));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_39] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_39, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(181, -33), "Guard House Child Pot 39", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_39)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_39] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_39, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(181, -33), "Guard House Child Pot 39", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_39));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_40] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_40, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -45), "Guard House Child Pot 40", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_40)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_40] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_40, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -45), "Guard House Child Pot 40", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_40));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_41] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_41, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(172, -82), "Guard House Child Pot 41", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_41)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_41] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_41, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(172, -82), "Guard House Child Pot 41", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_41));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_42] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_42, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -120), "Guard House Child Pot 42", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_42)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_42] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_42, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -120), "Guard House Child Pot 42", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_42));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_43] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_43, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -166), "Guard House Child Pot 43", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_43)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_43] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_43, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -166), "Guard House Child Pot 43", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_43));
locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_44] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_44, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -216), "Guard House Child Pot 44", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_44)); locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_44] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_44, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -216), "Guard House Child Pot 44", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_44));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(61, 204), "Guard House Adult Pot 1", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_1)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(61, 204), "Guard House Adult Pot 1", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_1));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, 132), "Guard House Adult Pot 2", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_2)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, 132), "Guard House Adult Pot 2", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_2));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(74, 23), "Guard House Adult Pot 3", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_3)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(74, 23), "Guard House Adult Pot 3", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_3));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 4), "Guard House Adult Pot 4", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_4)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 4), "Guard House Adult Pot 4", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_4));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, -22), "Guard House Adult Pot 5", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_5)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, -22), "Guard House Adult Pot 5", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_5));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -151), "Guard House Adult Pot 6", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_6)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -151), "Guard House Adult Pot 6", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_6));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(79, -182), "Guard House Adult Pot 7", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_7)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(79, -182), "Guard House Adult Pot 7", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_7));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -198), "Guard House Adult Pot 8", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_8)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -198), "Guard House Adult Pot 8", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_8));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 210), "Guard House Adult Pot 9", RHT_POT_MARKET, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_9)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 210), "Guard House Adult Pot 9", RHT_POT_POE_SHOP, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_9));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -122), "Guard House Adult Pot 10", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_10)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -122), "Guard House Adult Pot 10", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_10));
locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -210), "Guard House Adult Pot 11", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_11)); locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -210), "Guard House Adult Pot 11", RHT_POT_POE_SHOP, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_11));
locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_1] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(100, 45), "Back Alley House Pot 1", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_1)); locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_1] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(100, 45), "Back Alley House Pot 1", RHT_POT_ALLEY_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_1));
locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_2] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(12, -180), "Back Alley House Pot 2", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_2)); locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_2] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(12, -180), "Back Alley House Pot 2", RHT_POT_ALLEY_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_2));
locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_3] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(-54, -180), "Back Alley House Pot 3", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_3)); locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_3] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(-54, -180), "Back Alley House Pot 3", RHT_POT_ALLEY_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_3));
locationTable[RC_KAK_NEAR_POTION_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(222, -377), "Near Potion Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_1)); locationTable[RC_KAK_NEAR_POTION_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(222, -377), "Near Potion Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_1));
locationTable[RC_KAK_NEAR_POTION_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(255, -366), "Near Potion Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_2)); locationTable[RC_KAK_NEAR_POTION_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(255, -366), "Near Potion Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_2));
locationTable[RC_KAK_NEAR_POTION_SHOP_POT_3] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(284, -356), "Near Potion Shop Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_3)); locationTable[RC_KAK_NEAR_POTION_SHOP_POT_3] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(284, -356), "Near Potion Shop Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_3));
@ -203,12 +203,12 @@ void Rando::StaticData::RegisterPotLocations() {
locationTable[RC_KAK_NEAR_GUARDS_HOUSE_POT_3] = Location::Pot(RC_KAK_NEAR_GUARDS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-450, -895), "Near Guards House Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GUARDS_HOUSE_POT_3)); locationTable[RC_KAK_NEAR_GUARDS_HOUSE_POT_3] = Location::Pot(RC_KAK_NEAR_GUARDS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-450, -895), "Near Guards House Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GUARDS_HOUSE_POT_3));
locationTable[RC_KAK_NEAR_MEDICINE_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_MEDICINE_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(781, 89), "Near Medicine Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_MEDICINE_SHOP_POT_1)); locationTable[RC_KAK_NEAR_MEDICINE_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_MEDICINE_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(781, 89), "Near Medicine Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_MEDICINE_SHOP_POT_1));
locationTable[RC_KAK_NEAR_MEDICINE_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_MEDICINE_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(815, 89), "Near Medicine Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_MEDICINE_SHOP_POT_2)); locationTable[RC_KAK_NEAR_MEDICINE_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_MEDICINE_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(815, 89), "Near Medicine Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_MEDICINE_SHOP_POT_2));
locationTable[RC_GY_DAMPES_GRAVE_POT_1] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_1, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1542), "Dampes Grave Pot 1", RHT_POT_GRAVEYARD, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_1)); locationTable[RC_GY_DAMPES_GRAVE_POT_1] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_1, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1542), "Dampes Grave Pot 1", RHT_POT_DAMPE, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_1));
locationTable[RC_GY_DAMPES_GRAVE_POT_2] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_2, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1600), "Dampes Grave Pot 2", RHT_POT_GRAVEYARD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_2)); locationTable[RC_GY_DAMPES_GRAVE_POT_2] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_2, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1600), "Dampes Grave Pot 2", RHT_POT_DAMPE, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_2));
locationTable[RC_GY_DAMPES_GRAVE_POT_3] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_3, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-364, -1571), "Dampes Grave Pot 3", RHT_POT_GRAVEYARD, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_3)); locationTable[RC_GY_DAMPES_GRAVE_POT_3] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_3, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-364, -1571), "Dampes Grave Pot 3", RHT_POT_DAMPE, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_3));
locationTable[RC_GY_DAMPES_GRAVE_POT_4] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_4, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1540), "Dampes Grave Pot 4", RHT_POT_GRAVEYARD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_4)); locationTable[RC_GY_DAMPES_GRAVE_POT_4] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_4, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1540), "Dampes Grave Pot 4", RHT_POT_DAMPE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_4));
locationTable[RC_GY_DAMPES_GRAVE_POT_5] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_5, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1608), "Dampes Grave Pot 5", RHT_POT_GRAVEYARD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_5)); locationTable[RC_GY_DAMPES_GRAVE_POT_5] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_5, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1608), "Dampes Grave Pot 5", RHT_POT_DAMPE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_5));
locationTable[RC_GY_DAMPES_GRAVE_POT_6] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_6, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(239, -1577), "Dampes Grave Pot 6", RHT_POT_GRAVEYARD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_6)); locationTable[RC_GY_DAMPES_GRAVE_POT_6] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_6, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(239, -1577), "Dampes Grave Pot 6", RHT_POT_DAMPE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_6));
locationTable[RC_GC_LOWER_STAIRCASE_POT_1] = Location::Pot(RC_GC_LOWER_STAIRCASE_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-189, 866), "Lower Staircase Pot 1", RHT_POT_GORON_CITY, RG_DEKU_STICK_1, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_LOWER_STAIRCASE_POT_1)); locationTable[RC_GC_LOWER_STAIRCASE_POT_1] = Location::Pot(RC_GC_LOWER_STAIRCASE_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-189, 866), "Lower Staircase Pot 1", RHT_POT_GORON_CITY, RG_DEKU_STICK_1, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_LOWER_STAIRCASE_POT_1));
locationTable[RC_GC_LOWER_STAIRCASE_POT_2] = Location::Pot(RC_GC_LOWER_STAIRCASE_POT_2, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-271, 825), "Lower Staircase Pot 2", RHT_POT_GORON_CITY, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_LOWER_STAIRCASE_POT_2)); locationTable[RC_GC_LOWER_STAIRCASE_POT_2] = Location::Pot(RC_GC_LOWER_STAIRCASE_POT_2, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-271, 825), "Lower Staircase Pot 2", RHT_POT_GORON_CITY, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_LOWER_STAIRCASE_POT_2));
locationTable[RC_GC_UPPER_STAIRCASE_POT_1] = Location::Pot(RC_GC_UPPER_STAIRCASE_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-1170, 60), "Upper Staircase Pot 1", RHT_POT_GORON_CITY, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_UPPER_STAIRCASE_POT_1)); locationTable[RC_GC_UPPER_STAIRCASE_POT_1] = Location::Pot(RC_GC_UPPER_STAIRCASE_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-1170, 60), "Upper Staircase Pot 1", RHT_POT_GORON_CITY, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_UPPER_STAIRCASE_POT_1));
@ -241,15 +241,15 @@ void Rando::StaticData::RegisterPotLocations() {
locationTable[RC_LLR_RAIN_SHED_POT_1] = Location::Pot(RC_LLR_RAIN_SHED_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(852, 172), "Rain Shed Pot 1", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_1)); locationTable[RC_LLR_RAIN_SHED_POT_1] = Location::Pot(RC_LLR_RAIN_SHED_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(852, 172), "Rain Shed Pot 1", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_1));
locationTable[RC_LLR_RAIN_SHED_POT_2] = Location::Pot(RC_LLR_RAIN_SHED_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(840, 212), "Rain Shed Pot 2", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_2)); locationTable[RC_LLR_RAIN_SHED_POT_2] = Location::Pot(RC_LLR_RAIN_SHED_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(840, 212), "Rain Shed Pot 2", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_2));
locationTable[RC_LLR_RAIN_SHED_POT_3] = Location::Pot(RC_LLR_RAIN_SHED_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(872, 219), "Rain Shed Pot 3", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_3)); locationTable[RC_LLR_RAIN_SHED_POT_3] = Location::Pot(RC_LLR_RAIN_SHED_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(872, 219), "Rain Shed Pot 3", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_3));
locationTable[RC_LLR_TALONS_HOUSE_POT_1] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1255, 47), "Talons House Pot 1", RHT_POT_LON_LON_RANCH, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_1)); locationTable[RC_LLR_TALONS_HOUSE_POT_1] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1255, 47), "Talons House Pot 1", RHT_POT_TALONS_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_1));
locationTable[RC_LLR_TALONS_HOUSE_POT_2] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -51), "Talons House Pot 2", RHT_POT_LON_LON_RANCH, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_2)); locationTable[RC_LLR_TALONS_HOUSE_POT_2] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -51), "Talons House Pot 2", RHT_POT_TALONS_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_2));
locationTable[RC_LLR_TALONS_HOUSE_POT_3] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -78), "Talons House Pot 3", RHT_POT_LON_LON_RANCH, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_3)); locationTable[RC_LLR_TALONS_HOUSE_POT_3] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -78), "Talons House Pot 3", RHT_POT_TALONS_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_3));
locationTable[RC_HF_COW_GROTTO_POT_1] = Location::Pot(RC_HF_COW_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3410, -223), "Cow Grotto Pot 1", RHT_POT_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_1)); locationTable[RC_HF_COW_GROTTO_POT_1] = Location::Pot(RC_HF_COW_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3410, -223), "Cow Grotto Pot 1", RHT_POT_WEB_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_1));
locationTable[RC_HF_COW_GROTTO_POT_2] = Location::Pot(RC_HF_COW_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3390, -258), "Cow Grotto Pot 2", RHT_POT_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_2)); locationTable[RC_HF_COW_GROTTO_POT_2] = Location::Pot(RC_HF_COW_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3390, -258), "Cow Grotto Pot 2", RHT_POT_WEB_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_2));
locationTable[RC_HC_STORMS_GROTTO_POT_1] = Location::Pot(RC_HC_STORMS_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1843, 1014), "Storms Grotto Pot 1", RHT_POT_HYRULE_CASTLE, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_1)); locationTable[RC_HC_STORMS_GROTTO_POT_1] = Location::Pot(RC_HC_STORMS_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1843, 1014), "Storms Grotto Pot 1", RHT_POT_MUD_WALL_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_1));
locationTable[RC_HC_STORMS_GROTTO_POT_2] = Location::Pot(RC_HC_STORMS_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1769, 954), "Storms Grotto Pot 2", RHT_POT_HYRULE_CASTLE, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_2)); locationTable[RC_HC_STORMS_GROTTO_POT_2] = Location::Pot(RC_HC_STORMS_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1769, 954), "Storms Grotto Pot 2", RHT_POT_MUD_WALL_GROTTO, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_2));
locationTable[RC_HC_STORMS_GROTTO_POT_3] = Location::Pot(RC_HC_STORMS_GROTTO_POT_3, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1857, 897), "Storms Grotto Pot 3", RHT_POT_HYRULE_CASTLE, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_3)); locationTable[RC_HC_STORMS_GROTTO_POT_3] = Location::Pot(RC_HC_STORMS_GROTTO_POT_3, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1857, 897), "Storms Grotto Pot 3", RHT_POT_MUD_WALL_GROTTO, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_3));
locationTable[RC_HC_STORMS_GROTTO_POT_4] = Location::Pot(RC_HC_STORMS_GROTTO_POT_4, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1764, 847), "Storms Grotto Pot 4", RHT_POT_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_4)); locationTable[RC_HC_STORMS_GROTTO_POT_4] = Location::Pot(RC_HC_STORMS_GROTTO_POT_4, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1764, 847), "Storms Grotto Pot 4", RHT_POT_MUD_WALL_GROTTO, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_4));
// Dungeon Pots // Dungeon Pots
// Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Hint Text Key Vanilla Spoiler Collection Check // Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Hint Text Key Vanilla Spoiler Collection Check

View file

@ -1,13 +1,17 @@
#include <libultraship/bridge.h>
#include "draw.h" #include "draw.h"
#include "z64.h"
#include "macros.h"
#include "functions.h"
#include "variables.h"
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h" #include "soh/cvar_prefixes.h"
#include "randomizerTypes.h" #include "randomizerTypes.h"
#include <array> #include <array>
#include "soh_assets.h"
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
extern "C" {
#include "z64.h"
#include "macros.h"
#include "functions.h"
#include "variables.h"
#include "dungeon.h"
#include "objects/object_gi_key/object_gi_key.h" #include "objects/object_gi_key/object_gi_key.h"
#include "objects/object_gi_bosskey/object_gi_bosskey.h" #include "objects/object_gi_bosskey/object_gi_bosskey.h"
#include "objects/object_gi_compass/object_gi_compass.h" #include "objects/object_gi_compass/object_gi_compass.h"
@ -30,11 +34,6 @@
#include "overlays/ovl_Boss_Sst/ovl_Boss_Sst.h" #include "overlays/ovl_Boss_Sst/ovl_Boss_Sst.h"
#include "objects/object_tw/object_tw.h" #include "objects/object_tw/object_tw.h"
#include "objects/object_ganon2/object_ganon2.h" #include "objects/object_ganon2/object_ganon2.h"
#include "soh_assets.h"
#include "dungeon.h"
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
extern "C" {
extern PlayState* gPlayState; extern PlayState* gPlayState;
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }

View file

@ -45,8 +45,6 @@ std::string Entrance::GetName() const {
} }
void Entrance::printAgeTimeAccess() { void Entrance::printAgeTimeAccess() {
// CitraPrint("Name: ");
// CitraPrint(name);
auto message = "Child Day: " + std::to_string(CheckConditionAtAgeTime(logic->IsChild, logic->AtDay)) + auto message = "Child Day: " + std::to_string(CheckConditionAtAgeTime(logic->IsChild, logic->AtDay)) +
"\t" "\t"
"Child Night: " + "Child Night: " +
@ -57,7 +55,6 @@ void Entrance::printAgeTimeAccess() {
"\t" "\t"
"Adult Night: " + "Adult Night: " +
std::to_string(CheckConditionAtAgeTime(logic->IsAdult, logic->AtNight)); std::to_string(CheckConditionAtAgeTime(logic->IsAdult, logic->AtNight));
// CitraPrint(message);
} }
bool Entrance::ConditionsMet(bool allAgeTimes) const { bool Entrance::ConditionsMet(bool allAgeTimes) const {
@ -276,8 +273,8 @@ void SetAllEntrancesData() {
{ EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } }, { EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } },
{ { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE }, { { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE },
{ EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } }, { EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } },
{ { EntranceType::Dungeon, RR_GF_OUTSIDE_GTG, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE }, { { EntranceType::Dungeon, RR_GF_TO_GTG, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE },
{ EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GF_OUTSIDE_GTG, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } }, { EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GF_EXITING_GTG, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } },
{ { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE }, { { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE },
{ EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT } }, { EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT } },
@ -1214,15 +1211,6 @@ int EntranceShuffler::ShuffleAllEntrances() {
if (ctx->GetOption(RSK_SHUFFLE_BOSS_ENTRANCES).Is(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL)) { if (ctx->GetOption(RSK_SHUFFLE_BOSS_ENTRANCES).Is(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL)) {
entrancePools[EntranceType::Boss] = GetShuffleableEntrances(EntranceType::ChildBoss); entrancePools[EntranceType::Boss] = GetShuffleableEntrances(EntranceType::ChildBoss);
AddElementsToPool(entrancePools[EntranceType::Boss], GetShuffleableEntrances(EntranceType::AdultBoss)); AddElementsToPool(entrancePools[EntranceType::Boss], GetShuffleableEntrances(EntranceType::AdultBoss));
// If forest is closed, ensure Ghoma is inside the Deku tree
// Deku tree being in its vanilla location is handled below
if (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_ON) &&
!(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES))) {
FilterAndEraseFromPool(entrancePools[EntranceType::Boss], [](const Entrance* entrance) {
return entrance->GetParentRegionKey() == RR_DEKU_TREE_BOSS_ENTRYWAY &&
entrance->GetConnectedRegionKey() == RR_DEKU_TREE_BOSS_ROOM;
});
}
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
for (Entrance* entrance : entrancePools[EntranceType::Boss]) { for (Entrance* entrance : entrancePools[EntranceType::Boss]) {
entrancePools[EntranceType::BossReverse].push_back(entrance->GetReverse()); entrancePools[EntranceType::BossReverse].push_back(entrance->GetReverse());
@ -1231,14 +1219,6 @@ int EntranceShuffler::ShuffleAllEntrances() {
} else { } else {
entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss); entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss);
entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss); entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss);
// If forest is closed, ensure Ghoma is inside the Deku tree
if (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_ON) &&
!(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES))) {
FilterAndEraseFromPool(entrancePools[EntranceType::ChildBoss], [](const Entrance* entrance) {
return entrance->GetParentRegionKey() == RR_DEKU_TREE_BOSS_ENTRYWAY &&
entrance->GetConnectedRegionKey() == RR_DEKU_TREE_BOSS_ROOM;
});
}
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
for (Entrance* entrance : entrancePools[EntranceType::ChildBoss]) { for (Entrance* entrance : entrancePools[EntranceType::ChildBoss]) {
entrancePools[EntranceType::ChildBossReverse].push_back(entrance->GetReverse()); entrancePools[EntranceType::ChildBossReverse].push_back(entrance->GetReverse());
@ -1258,14 +1238,6 @@ int EntranceShuffler::ShuffleAllEntrances() {
AddElementsToPool(entrancePools[EntranceType::Dungeon], AddElementsToPool(entrancePools[EntranceType::Dungeon],
GetShuffleableEntrances(EntranceType::GanonDungeon)); GetShuffleableEntrances(EntranceType::GanonDungeon));
} }
// If forest is closed don't allow a forest escape via spirit temple hands
if (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_ON) &&
!(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES))) {
FilterAndEraseFromPool(entrancePools[EntranceType::Dungeon], [](const Entrance* entrance) {
return entrance->GetParentRegionKey() == RR_KF_OUTSIDE_DEKU_TREE &&
entrance->GetConnectedRegionKey() == RR_DEKU_TREE_ENTRYWAY;
});
}
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
for (Entrance* entrance : entrancePools[EntranceType::Dungeon]) { for (Entrance* entrance : entrancePools[EntranceType::Dungeon]) {
entrancePools[EntranceType::DungeonReverse].push_back(entrance->GetReverse()); entrancePools[EntranceType::DungeonReverse].push_back(entrance->GetReverse());

View file

@ -300,6 +300,8 @@ const CustomMessage Hint::GetHintMessage(MessageFormat format, size_t id) const
} else if (hintType == HINT_TYPE_ALTAR_CHILD) { } else if (hintType == HINT_TYPE_ALTAR_CHILD) {
if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) {
hintText = StaticData::hintTextTable[RHT_CHILD_ALTAR_STONES].GetHintMessage(); hintText = StaticData::hintTextTable[RHT_CHILD_ALTAR_STONES].GetHintMessage();
} else {
hintText.SetTextBoxType(TEXTBOX_TYPE_BLUE);
} }
if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN)) { if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN)) {
hintText += CustomMessage(StaticData::hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN].GetHintMessage()); hintText += CustomMessage(StaticData::hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN].GetHintMessage());
@ -311,6 +313,8 @@ const CustomMessage Hint::GetHintMessage(MessageFormat format, size_t id) const
} else if (hintType == HINT_TYPE_ALTAR_ADULT) { } else if (hintType == HINT_TYPE_ALTAR_ADULT) {
if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) {
hintText = StaticData::hintTextTable[RHT_ADULT_ALTAR_MEDALLIONS].GetHintMessage(); hintText = StaticData::hintTextTable[RHT_ADULT_ALTAR_MEDALLIONS].GetHintMessage();
} else {
hintText.SetTextBoxType(TEXTBOX_TYPE_BLUE);
} }
hintText += GetBridgeReqsText() + GetGanonBossKeyText() + hintText += GetBridgeReqsText() + GetGanonBossKeyText() +
StaticData::hintTextTable[RHT_ADULT_ALTAR_TEXT_END].GetHintMessage(); StaticData::hintTextTable[RHT_ADULT_ALTAR_TEXT_END].GetHintMessage();

View file

@ -22,6 +22,7 @@ extern "C" {
#include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h"
#include "soh/Enhancements/randomizer/randomizer_grotto.h" #include "soh/Enhancements/randomizer/randomizer_grotto.h"
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" #include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
#include "src/overlays/actors/ovl_Bg_Jya_Bigmirror/z_bg_jya_bigmirror.h"
#include "src/overlays/actors/ovl_En_Si/z_en_si.h" #include "src/overlays/actors/ovl_En_Si/z_en_si.h"
#include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h" #include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h"
#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h" #include "src/overlays/actors/ovl_En_Dns/z_en_dns.h"
@ -263,6 +264,14 @@ void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t
Flags_SetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN); Flags_SetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN);
} }
if (sceneNum == SCENE_SPIRIT_TEMPLE && flagType == FLAG_SCENE_SWITCH) {
bool isVanilla =
Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla();
if (isVanilla && flag == 0x23) {
Flags_SetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON);
}
}
RandomizerCheck rc = GetRandomizerCheckFromSceneFlag(sceneNum, flagType, flag); RandomizerCheck rc = GetRandomizerCheckFromSceneFlag(sceneNum, flagType, flag);
if (rc == RC_UNKNOWN_CHECK) if (rc == RC_UNKNOWN_CHECK)
return; return;
@ -1783,7 +1792,7 @@ void RandomizerOnSceneInitHandler(int16_t sceneNum) {
Entrance_OverrideSpawnScene(sceneNum, gPlayState->curSpawn); Entrance_OverrideSpawnScene(sceneNum, gPlayState->curSpawn);
} }
// LACs & Prelude checks // LACS & Prelude checks
static uint32_t updateHook = 0; static uint32_t updateHook = 0;
if (updateHook) { if (updateHook) {
@ -1855,6 +1864,16 @@ void EnDns_RandomizerPurchase(EnDns* enDns) {
void RandomizerOnActorInitHandler(void* actorRef) { void RandomizerOnActorInitHandler(void* actorRef) {
Actor* actor = static_cast<Actor*>(actorRef); Actor* actor = static_cast<Actor*>(actorRef);
if (actor->id == ACTOR_PLAYER) {
if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE) {
bool isVanilla =
Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla();
if (isVanilla && Flags_GetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON)) {
Flags_SetSwitch(gPlayState, 0x23);
}
}
}
if (actor->id == ACTOR_EN_SI) { if (actor->id == ACTOR_EN_SI) {
RandomizerCheck rc = RandomizerCheck rc =
OTRGlobals::Instance->gRandomizer->GetCheckFromActor(actor->id, gPlayState->sceneNum, actor->params); OTRGlobals::Instance->gRandomizer->GetCheckFromActor(actor->id, gPlayState->sceneNum, actor->params);
@ -1986,6 +2005,15 @@ void RandomizerOnActorInitHandler(void* actorRef) {
} }
} }
if (actor->id == ACTOR_BG_JYA_BIGMIRROR && Flags_GetRandomizerInf(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED)) {
Flags_SetSwitch(gPlayState, 0x29); // destroy wall
auto jyaBigMirror = static_cast<BgJyaBigmirror*>(actorRef);
jyaBigMirror->puzzleFlags |=
BIGMIR_PUZZLE_COBRA1_SOLVED | BIGMIR_PUZZLE_COBRA2_SOLVED | BIGMIR_PUZZLE_BOMBIWA_DESTROYED;
jyaBigMirror->cobraInfo[0].rotY = 0x4000;
jyaBigMirror->cobraInfo[1].rotY = 0x8000;
}
if (actor->id == ACTOR_DEMO_KEKKAI && actor->params == 0) { // 0 == KEKKAI_TOWER if (actor->id == ACTOR_DEMO_KEKKAI && actor->params == 0) { // 0 == KEKKAI_TOWER
if (CompletedAllTrials()) { if (CompletedAllTrials()) {
Actor_Kill(actor); Actor_Kill(actor);
@ -2151,6 +2179,16 @@ void RandomizerOnActorUpdateHandler(void* refActor) {
} }
} }
if (actor->id == ACTOR_BG_JYA_BIGMIRROR) {
auto jyaBigMirror = reinterpret_cast<BgJyaBigmirror*>(actor);
if ((jyaBigMirror->puzzleFlags & (BIGMIR_PUZZLE_COBRA1_SOLVED | BIGMIR_PUZZLE_COBRA2_SOLVED)) ==
(BIGMIR_PUZZLE_COBRA1_SOLVED | BIGMIR_PUZZLE_COBRA2_SOLVED)) {
Flags_SetRandomizerInf(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED);
} else {
Flags_UnsetRandomizerInf(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED);
}
}
// In ER, override the warp song locations. Also removes the warp song cutscene // In ER, override the warp song locations. Also removes the warp song cutscene
if (RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES) && actor->id == ACTOR_DEMO_KANKYO && if (RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES) && actor->id == ACTOR_DEMO_KANKYO &&
actor->params == 0x000F) { // Warp Song particles actor->params == 0x000F) { // Warp Song particles

View file

@ -20,6 +20,8 @@ Item::Item(const RandomizerGet randomizerGet_, const ItemType type_, const int16
const GetItemCategory category_, const uint16_t modIndex_, const uint16_t price_, const GetItemCategory category_, const uint16_t modIndex_, const uint16_t price_,
const CustomDrawFunc drawfunc_) const CustomDrawFunc drawfunc_)
: randomizerGet(randomizerGet_), type(type_), getItemId(getItemId_), logicVal(logicVal_), hintKey(hintKey_), : randomizerGet(randomizerGet_), type(type_), getItemId(getItemId_), logicVal(logicVal_), hintKey(hintKey_),
category(category_),
price(price_) { price(price_) {
if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) { if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) {
giEntry = std::make_shared<GetItemEntry>(GetItemEntry{ giEntry = std::make_shared<GetItemEntry>(GetItemEntry{
@ -39,7 +41,7 @@ Item::Item(const RandomizerGet randomizerGet_, const ItemType type_, const int16
const uint16_t field_, const int16_t chestAnimation_, const GetItemCategory category_, const uint16_t field_, const int16_t chestAnimation_, const GetItemCategory category_,
const uint16_t modIndex_, const uint16_t price_, const CustomDrawFunc drawfunc_) const uint16_t modIndex_, const uint16_t price_, const CustomDrawFunc drawfunc_)
: randomizerGet(randomizerGet_), type(type_), getItemId(getItemId_), logicVal(logicVal_), hintKey(hintKey_), : randomizerGet(randomizerGet_), type(type_), getItemId(getItemId_), logicVal(logicVal_), hintKey(hintKey_),
price(price_) { category(category_), price(price_) {
if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) { if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) {
giEntry = std::make_shared<GetItemEntry>( giEntry = std::make_shared<GetItemEntry>(
GetItemEntry{ static_cast<uint16_t>(randomizerGet_), field_, GetItemEntry{ static_cast<uint16_t>(randomizerGet_), field_,
@ -56,7 +58,7 @@ Item::Item(const RandomizerGet randomizerGet_, const ItemType type_, const int16
} }
Item::Item(const RandomizerGet randomizerGet_, const ItemType type_, const int16_t getItemId_, LogicVal logicVal_, Item::Item(const RandomizerGet randomizerGet_, const ItemType type_, const int16_t getItemId_, LogicVal logicVal_,
const RandomizerHintTextKey hintKey_, const uint16_t price_) const RandomizerHintTextKey hintKey_, const GetItemCategory category_, const uint16_t price_)
: randomizerGet(randomizerGet_), type(type_), getItemId(getItemId_), logicVal(logicVal_), hintKey(hintKey_), : randomizerGet(randomizerGet_), type(type_), getItemId(getItemId_), logicVal(logicVal_), hintKey(hintKey_),
price(price_) { price(price_) {
} }
@ -467,6 +469,10 @@ const HintText& Item::GetHint() const {
return StaticData::hintTextTable[hintKey]; return StaticData::hintTextTable[hintKey];
} }
GetItemCategory Item::GetCategory() {
return category;
}
bool Item::operator==(const Item& right) const { bool Item::operator==(const Item& right) const {
return type == right.GetItemType() && getItemId == right.GetItemID(); return type == right.GetItemType() && getItemId == right.GetItemID();
} }

View file

@ -39,7 +39,7 @@ class Item {
int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_, uint16_t price_ = 0, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_, uint16_t price_ = 0,
CustomDrawFunc drawfunc_ = NULL); CustomDrawFunc drawfunc_ = NULL);
Item(RandomizerGet randomizerGet_, ItemType type_, int16_t getItemId_, LogicVal logicVal_, Item(RandomizerGet randomizerGet_, ItemType type_, int16_t getItemId_, LogicVal logicVal_,
RandomizerHintTextKey hintKey_, uint16_t price_ = 0); RandomizerHintTextKey hintKey_, GetItemCategory category_, uint16_t price_ = 0);
~Item(); ~Item();
void ApplyEffect() const; void ApplyEffect() const;
@ -60,6 +60,7 @@ class Item {
bool IsMajorItem() const; bool IsMajorItem() const;
RandomizerHintTextKey GetHintKey() const; RandomizerHintTextKey GetHintKey() const;
const HintText& GetHint() const; const HintText& GetHint() const;
GetItemCategory GetCategory();
bool operator==(const Item& right) const; bool operator==(const Item& right) const;
bool operator!=(const Item& right) const; bool operator!=(const Item& right) const;
@ -71,6 +72,7 @@ class Item {
bool advancement; bool advancement;
LogicVal logicVal; LogicVal logicVal;
RandomizerHintTextKey hintKey; RandomizerHintTextKey hintKey;
GetItemCategory category;
uint16_t price; uint16_t price;
std::shared_ptr<GetItemEntry> giEntry; std::shared_ptr<GetItemEntry> giEntry;
}; };

View file

@ -28,8 +28,9 @@ void Rando::StaticData::AddItem(const RandomizerGet randomizerGet_, const ItemTy
} }
void Rando::StaticData::AddItem(const RandomizerGet randomizerGet_, const ItemType type_, const int16_t getItemId_, void Rando::StaticData::AddItem(const RandomizerGet randomizerGet_, const ItemType type_, const int16_t getItemId_,
const LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const uint16_t price_) { const LogicVal logicVal_, const RandomizerHintTextKey hintKey_,
itemTable[randomizerGet_] = Item(randomizerGet_, type_, getItemId_, logicVal_, hintKey_, price_); const GetItemCategory category_, const uint16_t price_) {
itemTable[randomizerGet_] = Item(randomizerGet_, type_, getItemId_, logicVal_, hintKey_, category_, price_);
} }
void Rando::StaticData::InitItemTable() { void Rando::StaticData::InitItemTable() {
@ -77,19 +78,19 @@ void Rando::StaticData::InitItemTable() {
// Skulltula Token // Skulltula Token
AddItem(RG_GOLD_SKULLTULA_TOKEN, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULL_TOKEN, MOD_NONE); AddItem(RG_GOLD_SKULLTULA_TOKEN, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULL_TOKEN, MOD_NONE);
// Progressive Items // Progressive Items
AddItem(RG_PROGRESSIVE_HOOKSHOT, ITEMTYPE_ITEM, 0x80, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT); AddItem(RG_PROGRESSIVE_HOOKSHOT, ITEMTYPE_ITEM, 0x80, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, ITEM_CATEGORY_MAJOR); //
AddItem(RG_PROGRESSIVE_STRENGTH, ITEMTYPE_ITEM, 0x81, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH); AddItem(RG_PROGRESSIVE_STRENGTH, ITEMTYPE_ITEM, 0x81, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_BOMB_BAG, ITEMTYPE_ITEM, 0x82, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG); AddItem(RG_PROGRESSIVE_BOMB_BAG, ITEMTYPE_ITEM, 0x82, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_BOW, ITEMTYPE_ITEM, 0x83, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW); AddItem(RG_PROGRESSIVE_BOW, ITEMTYPE_ITEM, 0x83, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_SLINGSHOT, ITEMTYPE_ITEM, 0x84, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT); AddItem(RG_PROGRESSIVE_SLINGSHOT, ITEMTYPE_ITEM, 0x84, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_WALLET, ITEMTYPE_ITEM, 0x85, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET); AddItem(RG_PROGRESSIVE_WALLET, ITEMTYPE_ITEM, 0x85, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_SCALE, ITEMTYPE_ITEM, 0x86, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE); AddItem(RG_PROGRESSIVE_SCALE, ITEMTYPE_ITEM, 0x86, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_NUT_BAG, ITEMTYPE_ITEM, 0x87, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE); AddItem(RG_PROGRESSIVE_NUT_BAG, ITEMTYPE_ITEM, 0x87, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_STICK_BAG, ITEMTYPE_ITEM, 0x88, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE); AddItem(RG_PROGRESSIVE_STICK_BAG, ITEMTYPE_ITEM, 0x88, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_BOMBCHUS, ITEMTYPE_ITEM, 0x89, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS); AddItem(RG_PROGRESSIVE_BOMBCHUS, ITEMTYPE_ITEM, 0x89, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_MAGIC, ITEMTYPE_ITEM, 0x8A, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER); AddItem(RG_PROGRESSIVE_MAGIC, ITEMTYPE_ITEM, 0x8A, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_OCARINA, ITEMTYPE_ITEM, 0x8B, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA); AddItem(RG_PROGRESSIVE_OCARINA, ITEMTYPE_ITEM, 0x8B, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, ITEM_CATEGORY_MAJOR);
AddItem(RG_PROGRESSIVE_GORONSWORD, ITEMTYPE_ITEM, 0xD4, LOGIC_PROGRESSIVE_GORONSWORD, RHT_PROGRESSIVE_GORONSWORD); AddItem(RG_PROGRESSIVE_GORONSWORD, ITEMTYPE_ITEM, 0xD4, LOGIC_PROGRESSIVE_GORONSWORD, RHT_PROGRESSIVE_GORONSWORD, ITEM_CATEGORY_MAJOR);
// Bottles // Bottles
AddItem(RG_EMPTY_BOTTLE, ITEMTYPE_ITEM, GI_BOTTLE, LOGIC_BOTTLES, RHT_EMPTY_BOTTLE, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); AddItem(RG_EMPTY_BOTTLE, ITEMTYPE_ITEM, GI_BOTTLE, LOGIC_BOTTLES, RHT_EMPTY_BOTTLE, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
AddItem(RG_BOTTLE_WITH_MILK, ITEMTYPE_ITEM, GI_MILK_BOTTLE, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); AddItem(RG_BOTTLE_WITH_MILK, ITEMTYPE_ITEM, GI_MILK_BOTTLE, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
@ -255,7 +256,7 @@ void Rando::StaticData::InitItemTable() {
AddItem(RG_BUY_BOMBCHUS_10, ITEMTYPE_SHOP, GI_BOMBCHUS_10, LOGIC_BUY_BOMBCHUS, RHT_BUY_BOMBCHUS_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, 99); AddItem(RG_BUY_BOMBCHUS_10, ITEMTYPE_SHOP, GI_BOMBCHUS_10, LOGIC_BUY_BOMBCHUS, RHT_BUY_BOMBCHUS_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, 99);
AddItem(RG_BUY_BOMBCHUS_20, ITEMTYPE_SHOP, GI_BOMBCHUS_20, LOGIC_BUY_BOMBCHUS, RHT_BUY_BOMBCHUS_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, 180); AddItem(RG_BUY_BOMBCHUS_20, ITEMTYPE_SHOP, GI_BOMBCHUS_20, LOGIC_BUY_BOMBCHUS, RHT_BUY_BOMBCHUS_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, 180);
AddItem(RG_BUY_DEKU_SEEDS_30, ITEMTYPE_SHOP, GI_SEEDS_30, LOGIC_BUY_SEED, RHT_BUY_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, 30); AddItem(RG_BUY_DEKU_SEEDS_30, ITEMTYPE_SHOP, GI_SEEDS_30, LOGIC_BUY_SEED, RHT_BUY_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, 30);
AddItem(RG_SOLD_OUT, ITEMTYPE_SHOP, RG_SOLD_OUT, LOGIC_NONE, RHT_SOLD_OUT, 0); AddItem(RG_SOLD_OUT, ITEMTYPE_SHOP, RG_SOLD_OUT, LOGIC_NONE, RHT_SOLD_OUT, ITEM_CATEGORY_JUNK, 0);
AddItem(RG_BUY_BLUE_FIRE, ITEMTYPE_SHOP, GI_BLUE_FIRE, LOGIC_BLUE_FIRE_ACCESS, RHT_BUY_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, 300); AddItem(RG_BUY_BLUE_FIRE, ITEMTYPE_SHOP, GI_BLUE_FIRE, LOGIC_BLUE_FIRE_ACCESS, RHT_BUY_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, 300);
AddItem(RG_BUY_BOTTLE_BUG, ITEMTYPE_SHOP, GI_BUGS, LOGIC_BUGS_ACCESS, RHT_BUY_BOTTLE_BUG, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, 50); AddItem(RG_BUY_BOTTLE_BUG, ITEMTYPE_SHOP, GI_BUGS, LOGIC_BUGS_ACCESS, RHT_BUY_BOTTLE_BUG, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, 50);
AddItem(RG_BUY_POE, ITEMTYPE_SHOP, RG_BUY_POE, LOGIC_NONE, RHT_BUY_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, 30); AddItem(RG_BUY_POE, ITEMTYPE_SHOP, RG_BUY_POE, LOGIC_NONE, RHT_BUY_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, 30);
@ -298,8 +299,8 @@ void Rando::StaticData::InitItemTable() {
AddItem(RG_SKELETON_KEY, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, 0, Randomizer_DrawSkeletonKey); AddItem(RG_SKELETON_KEY, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, 0, Randomizer_DrawSkeletonKey);
AddItem(RG_TRIFORCE, ITEMTYPE_EVENT, RG_TRIFORCE, LOGIC_NONE, RHT_TRIFORCE); AddItem(RG_TRIFORCE, ITEMTYPE_EVENT, RG_TRIFORCE, LOGIC_NONE, RHT_TRIFORCE, ITEM_CATEGORY_MAJOR);
AddItem(RG_HINT, ITEMTYPE_EVENT, RG_HINT, LOGIC_NONE, RHT_HINT); AddItem(RG_HINT, ITEMTYPE_EVENT, RG_HINT, LOGIC_NONE, RHT_HINT, ITEM_CATEGORY_LESSER);
// Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen) // Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen)
AddItem(RG_HOOKSHOT, ITEMTYPE_ITEM, GI_HOOKSHOT, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); AddItem(RG_HOOKSHOT, ITEMTYPE_ITEM, GI_HOOKSHOT, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
AddItem(RG_LONGSHOT, ITEMTYPE_ITEM, GI_LONGSHOT, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); AddItem(RG_LONGSHOT, ITEMTYPE_ITEM, GI_LONGSHOT, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);

View file

@ -55,7 +55,8 @@ const std::string& Rando::Location::GetShortName() const {
bool Rando::Location::IsDungeon() const { bool Rando::Location::IsDungeon() const {
return (checkType != RCTYPE_SKULL_TOKEN && return (checkType != RCTYPE_SKULL_TOKEN &&
(scene <= SCENE_GERUDO_TRAINING_GROUND || scene == SCENE_INSIDE_GANONS_CASTLE || (scene <= SCENE_GERUDO_TRAINING_GROUND || scene == SCENE_INSIDE_GANONS_CASTLE ||
(scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_GANONDORF_BOSS))) || (scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_GANONDORF_BOSS)) ||
(rc == RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST || rc == RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST)) ||
(checkType == RCTYPE_SKULL_TOKEN && scene <= SCENE_ICE_CAVERN); (checkType == RCTYPE_SKULL_TOKEN && scene <= SCENE_ICE_CAVERN);
} }

View file

@ -20,6 +20,18 @@ extern PlayState* gPlayState;
// generic grotto event list // generic grotto event list
std::vector<EventAccess> grottoEvents; std::vector<EventAccess> grottoEvents;
bool EventAccess::CheckConditionAtAgeTime(bool& age, bool& time) {
logic->IsChild = false;
logic->IsAdult = false;
logic->AtDay = false;
logic->AtNight = false;
time = true;
age = true;
return ConditionsMet();
}
// set the logic to be a specific age and time of day and see if the condition still holds // set the logic to be a specific age and time of day and see if the condition still holds
bool LocationAccess::CheckConditionAtAgeTime(bool& age, bool& time) const { bool LocationAccess::CheckConditionAtAgeTime(bool& age, bool& time) const {
logic->IsChild = false; logic->IsChild = false;
@ -466,7 +478,7 @@ bool Region::UpdateEvents() {
} }
void Region::AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition) { void Region::AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition) {
Rando::Entrance newExit = Rando::Entrance(newExitKey, { condition }); Rando::Entrance newExit = Rando::Entrance(newExitKey, condition);
newExit.SetParentRegion(parentKey); newExit.SetParentRegion(parentKey);
exits.push_front(newExit); exits.push_front(newExit);
} }
@ -551,6 +563,110 @@ void Region::ResetVariables() {
} }
} }
/*
* This logic covers checks that exist in the shared areas of MQ spirit from a glitchless standpoint.
* This room has Quantum logic that I am currently handling with this function, however this is NOT suitable for
glitch logic as it relies on specific ages
* In this chunk there are 3 possibilities for passing a check, but first I have to talk about parallel universes.
* In MQ Spirit key logic, we mostly care about 2 possibilities for how the player can spend keys, creating 2
Parralel universes
* In the first universe, the player did not enter spirit as adult until after climbing as child, thus child spends
keys linearly, only needing 2 to reach statue room.
* In the second universe, the player went in as adult, possibly out of logic, and started wasting the keys to lock
child out.
* These Universes converge when the player has 7 keys (meaning adult can no longer lock child out) and adult is
known to be able to reach Statue room. This creates "Certain Access", which is tracked seperatly for each age.
* Child Certain Access is simple, if we have 7 keys and child access, it's Certain Access.
* Adult Certain Access is also simple, adult is not key locked, so if they make it to a location, it's Certain
Access.
* Things get complicated when we handle the overlap of the 2 universes,
* though an important detail is that if we have Certain Access as either age, we don't need to checked the overlap
because overlap logic is strictly stricter than either Certain Access.
* In order to track the first universe, the logic allows technical child access with the minimum number of keys,
and then checks in this function for if we have 7 keys to determine if that is Certain or not.
* This is for technical reasons, as areas with no access at all will simply not be checked.
* Normally we would need to do similar shenanigans to track the second universe, however adult must have go through
statue room to waste keys,
* so can go back there and get new keys for Child to use if they do, and the navigation logic for shared MQ spirit
from Statue Room is very simple for Adult.
* Additionally, we don't need to know if adult can actually reach spirit temple or climb to statue room, because if
the player can't do that, then universe 2 can't happen anyway,
* and if the player does so out of logic, they can do it again, as the only consumable used sets a permanent flag.
* The Adult Navigation logic is as such:
* - Broken Wall room is 6 key locked, because if the player tries to spend 6 keys in a way that would block adults
access, they would have to give child access instead.
* - The child side hammer switch for the time travelling chest is 7 key locked for adult
* - Reaching gauntlets hand is 7 key locked
* - Going back into big block room is complex, but the only check there is child only so not a concern
* - Everything else is possible with basic adult movement, or is impossible for child to reach glitchlessly
* Anything 7 key locked does not need to be checked as shared, as all child access is Certain and because of this
workaround we don't need to fake Adult access, meaning that is also Certain.
* All of this combined means that when checking if adult can reach a location in universe 2, we only have to ask if
it is a 6 key locked location or not.
* Knowing all of this this, we can confirm things are logical in 3 different ways:
* - If we have Adult Access, we know it is Certain Access, so they can get checks alone.
* - If we have 7 keys, child has Certain Access as we know they cannot be locked out, so can get checks alone,
otherwise we check the logical overlap
* - If Child and Adult can get the check (ignoring actual adult access to the location), and the location is either
not 6 key locked or we have 6 keys, we can get the check with the overlap
*/
bool Region::MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge) {
// if we have Certain Access as child, we can check anyAge and if true, resolve a condition with Here as if
// adult is here it's also Certain Access
if (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)) {
if (anyAge) {
return Here(condition);
}
return condition();
// else, if we are here as adult, we have Certain Access from that and don't need special handling for
// checking adult
} else if (Adult() && logic->IsAdult) {
return condition();
// if we do not have Certain Access, we need to check the overlap by seeing if we are both here as child and
// meet the adult universe's access condition We only need to do it as child, as only child access matters
// for this check, as adult access is assumed based on keys
} else if (Child() && logic->IsChild && (!IsBrokenWall || logic->SmallKeys(RR_SPIRIT_TEMPLE, 6))) {
bool result = false;
// store current age variables
bool pastAdult = logic->IsAdult;
bool pastChild = logic->IsChild;
// First check if the check is possible as child
logic->IsChild = true;
logic->IsAdult = false;
result = condition();
// If so, check again as adult. both have to be true for result to be true
if (result) {
logic->IsChild = false;
logic->IsAdult = true;
result = condition();
}
// set back age variables
logic->IsChild = pastChild;
logic->IsAdult = pastAdult;
return result;
}
return false;
}
void Region::printAgeTimeAccess() {
auto message = "Child Day: " + std::to_string(childDay) +
"\t"
"Child Night: " +
std::to_string(childNight) +
"\t"
"Adult Day: " +
std::to_string(adultDay) +
"\t"
"Adult Night: " +
std::to_string(adultNight);
}
std::array<Region, RR_MAX> areaTable; std::array<Region, RR_MAX> areaTable;
bool Here(const RandomizerRegion region, ConditionFn condition) { bool Here(const RandomizerRegion region, ConditionFn condition) {
@ -692,11 +808,11 @@ void RegionTable_Init() {
Entrance(RR_CHILD_SPAWN, []{return logic->IsChild;}), Entrance(RR_CHILD_SPAWN, []{return logic->IsChild;}),
Entrance(RR_ADULT_SPAWN, []{return logic->IsAdult;}), Entrance(RR_ADULT_SPAWN, []{return logic->IsAdult;}),
Entrance(RR_MINUET_OF_FOREST_WARP, []{return logic->CanUse(RG_MINUET_OF_FOREST);}), Entrance(RR_MINUET_OF_FOREST_WARP, []{return logic->CanUse(RG_MINUET_OF_FOREST);}),
Entrance(RR_BOLERO_OF_FIRE_WARP, []{return logic->CanUse(RG_BOLERO_OF_FIRE) && logic->CanLeaveForest();}), Entrance(RR_BOLERO_OF_FIRE_WARP, []{return logic->CanUse(RG_BOLERO_OF_FIRE);}),
Entrance(RR_SERENADE_OF_WATER_WARP, []{return logic->CanUse(RG_SERENADE_OF_WATER) && logic->CanLeaveForest();}), Entrance(RR_SERENADE_OF_WATER_WARP, []{return logic->CanUse(RG_SERENADE_OF_WATER);}),
Entrance(RR_NOCTURNE_OF_SHADOW_WARP, []{return logic->CanUse(RG_NOCTURNE_OF_SHADOW) && logic->CanLeaveForest();}), Entrance(RR_NOCTURNE_OF_SHADOW_WARP, []{return logic->CanUse(RG_NOCTURNE_OF_SHADOW);}),
Entrance(RR_REQUIEM_OF_SPIRIT_WARP, []{return logic->CanUse(RG_REQUIEM_OF_SPIRIT) && logic->CanLeaveForest();}), Entrance(RR_REQUIEM_OF_SPIRIT_WARP, []{return logic->CanUse(RG_REQUIEM_OF_SPIRIT);}),
Entrance(RR_PRELUDE_OF_LIGHT_WARP, []{return logic->CanUse(RG_PRELUDE_OF_LIGHT) && logic->CanLeaveForest();}), Entrance(RR_PRELUDE_OF_LIGHT_WARP, []{return logic->CanUse(RG_PRELUDE_OF_LIGHT);}),
}); });
areaTable[RR_CHILD_SPAWN] = Region("Child Spawn", SCENE_ID_MAX, TIME_DOESNT_PASS, {RA_LINKS_POCKET}, {}, {}, { areaTable[RR_CHILD_SPAWN] = Region("Child Spawn", SCENE_ID_MAX, TIME_DOESNT_PASS, {RA_LINKS_POCKET}, {}, {}, {

View file

@ -34,17 +34,7 @@ class EventAccess {
return true; return true;
} }
bool CheckConditionAtAgeTime(bool& age, bool& time) { bool CheckConditionAtAgeTime(bool& age, bool& time);
logic->IsChild = false;
logic->IsAdult = false;
logic->AtDay = false;
logic->AtNight = false;
time = true;
age = true;
return ConditionsMet();
}
void EventOccurred() { void EventOccurred() {
*event = true; *event = true;
@ -210,7 +200,7 @@ class Region {
logic->IsChild = Child(); logic->IsChild = Child();
logic->IsAdult = Adult(); logic->IsAdult = Adult();
// heck condition as well as having at least child or adult access // check condition as well as having at least child or adult access
bool hereVal = condition() && (logic->IsAdult || logic->IsChild); bool hereVal = condition() && (logic->IsAdult || logic->IsChild);
// set back age variables // set back age variables
@ -222,112 +212,11 @@ class Region {
bool CanPlantBeanCheck() const; bool CanPlantBeanCheck() const;
bool AllAccountedFor() const; bool AllAccountedFor() const;
bool MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge = false);
void ResetVariables(); void ResetVariables();
void printAgeTimeAccess() const { void printAgeTimeAccess();
auto message = "Child Day: " + std::to_string(childDay) +
"\t"
"Child Night: " +
std::to_string(childNight) +
"\t"
"Adult Day: " +
std::to_string(adultDay) +
"\t"
"Adult Night: " +
std::to_string(adultNight);
}
/*
* This logic covers checks that exist in the shared areas of MQ spirit from a glitchless standpoint.
* This room has Quantum logic that I am currently handling with this function, however this is NOT suitable for
glitch logic as it relies on specific ages
* In this chunk there are 3 possibilities for passing a check, but first I have to talk about parallel universes.
* In MQ Spirit key logic, we mostly care about 2 possibilities for how the player can spend keys, creating 2
Parralel universes
* In the first universe, the player did not enter spirit as adult until after climbing as child, thus child spends
keys linearly, only needing 2 to reach statue room.
* In the second universe, the player went in as adult, possibly out of logic, and started wasting the keys to lock
child out.
* These Universes converge when the player has 7 keys (meaning adult can no longer lock child out) and adult is
known to be able to reach Statue room. This creates "Certain Access", which is tracked seperatly for each age.
* Child Certain Access is simple, if we have 7 keys and child access, it's Certain Access.
* Adult Certain Access is also simple, adult is not key locked, so if they make it to a location, it's Certain
Access.
* Things get complicated when we handle the overlap of the 2 universes,
* though an important detail is that if we have Certain Access as either age, we don't need to checked the overlap
because overlap logic is strictly stricter than either Certain Access.
* In order to track the first universe, the logic allows technical child access with the minimum number of keys,
and then checks in this function for if we have 7 keys to determine if that is Certain or not.
* This is for technical reasons, as areas with no access at all will simply not be checked.
* Normally we would need to do similar shenanigans to track the second universe, however adult must have go through
statue room to waste keys,
* so can go back there and get new keys for Child to use if they do, and the navigation logic for shared MQ spirit
from Statue Room is very simple for Adult.
* Additionally, we don't need to know if adult can actually reach spirit temple or climb to statue room, because if
the player can't do that, then universe 2 can't happen anyway,
* and if the player does so out of logic, they can do it again, as the only consumable used sets a permanent flag.
* The Adult Navigation logic is as such:
* - Broken Wall room is 6 key locked, because if the player tries to spend 6 keys in a way that would block adults
access, they would have to give child access instead.
* - The child side hammer switch for the time travelling chest is 7 key locked for adult
* - Reaching gauntlets hand is 7 key locked
* - Going back into big block room is complex, but the only check there is child only so not a concern
* - Everything else is possible with basic adult movement, or is impossible for child to reach glitchlessly
* Anything 7 key locked does not need to be checked as shared, as all child access is Certain and because of this
workaround we don't need to fake Adult access, meaning that is also Certain.
* All of this combined means that when checking if adult can reach a location in universe 2, we only have to ask if
it is a 6 key locked location or not.
* Knowing all of this this, we can confirm things are logical in 3 different ways:
* - If we have Adult Access, we know it is Certain Access, so they can get checks alone.
* - If we have 7 keys, child has Certain Access as we know they cannot be locked out, so can get checks alone,
otherwise we check the logical overlap
* - If Child and Adult can get the check (ignoring actual adult access to the location), and the location is either
not 6 key locked or we have 6 keys, we can get the check with the overlap
*/
bool MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge = false) {
// if we have Certain Access as child, we can check anyAge and if true, resolve a condition with Here as if
// adult is here it's also Certain Access
if (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)) {
if (anyAge) {
return Here(condition);
}
return condition();
// else, if we are here as adult, we have Certain Access from that and don't need special handling for
// checking adult
} else if (Adult() && logic->IsAdult) {
return condition();
// if we do not have Certain Access, we need to check the overlap by seeing if we are both here as child and
// meet the adult universe's access condition We only need to do it as child, as only child access matters
// for this check, as adult access is assumed based on keys
} else if (Child() && logic->IsChild && (!IsBrokenWall || logic->SmallKeys(RR_SPIRIT_TEMPLE, 6))) {
bool result = false;
// store current age variables
bool pastAdult = logic->IsAdult;
bool pastChild = logic->IsChild;
// First check if the check is possible as child
logic->IsChild = true;
logic->IsAdult = false;
result = condition();
// If so, check again as adult. both have to be true for result to be true
if (result) {
logic->IsChild = false;
logic->IsAdult = true;
result = condition();
}
// set back age variables
logic->IsChild = pastChild;
logic->IsAdult = pastAdult;
return result;
}
return false;
}
}; };
extern std::array<Region, RR_MAX> areaTable; extern std::array<Region, RR_MAX> areaTable;

View file

@ -11,7 +11,7 @@ void RegionTable_Init_GerudoTrainingGround() {
//Exits //Exits
Entrance(RR_GERUDO_TRAINING_GROUND_LOBBY, []{return ctx->GetDungeon(GERUDO_TRAINING_GROUND)->IsVanilla();}), Entrance(RR_GERUDO_TRAINING_GROUND_LOBBY, []{return ctx->GetDungeon(GERUDO_TRAINING_GROUND)->IsVanilla();}),
Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return ctx->GetDungeon(GERUDO_TRAINING_GROUND)->IsMQ();}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return ctx->GetDungeon(GERUDO_TRAINING_GROUND)->IsMQ();}),
Entrance(RR_GF_OUTSIDE_GTG, []{return true;}), Entrance(RR_GF_EXITING_GTG, []{return true;}),
}); });
#pragma region Vanilla #pragma region Vanilla

View file

@ -64,7 +64,7 @@ void RegionTable_Init_JabuJabusBelly() {
//Exits //Exits
Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return true;}), Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return true;}),
//there's tricks for getting here with bunny-jumps or just side-hops //there's tricks for getting here with bunny-jumps or just side-hops
Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}), Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}),
}); });
@ -90,7 +90,7 @@ void RegionTable_Init_JabuJabusBelly() {
}, { }, {
//Exits //Exits
Entrance(RR_JABU_JABUS_BELLY_B1_NORTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), Entrance(RR_JABU_JABUS_BELLY_B1_NORTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}),
Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}), Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return logic->CanUseProjectile();}), Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return logic->CanUseProjectile();}),
}); });

View file

@ -48,12 +48,12 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Region("Child Spirit Temple Climb", SCENE_SPIRIT_TEMPLE, {}, { areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Region("Child Spirit Temple Climb", SCENE_SPIRIT_TEMPLE, {}, {
//Locations //Locations
LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))),
LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))), LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))),
LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, logic->HasProjectile(HasProjectileAge::Both) || logic->CanUse(RG_DINS_FIRE) || LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, logic->HasProjectile(HasProjectileAge::Both) || logic->CanUse(RG_DINS_FIRE) ||
(logic->TakeDamage() && (logic->CanJumpslashExceptHammer() || logic->HasProjectile(HasProjectileAge::Child))) || (logic->TakeDamage() && (logic->CanJumpslashExceptHammer() || logic->HasProjectile(HasProjectileAge::Child))) ||
(logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasProjectile(HasProjectileAge::Child)) || (logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasProjectile(HasProjectileAge::Child)) ||
((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->TakeDamage() && logic->CanJumpslashExceptHammer())))), (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->TakeDamage() && logic->CanJumpslashExceptHammer())))),
LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_POT_1, logic->CanBreakPots()),
}, { }, {
//Exits //Exits
@ -75,11 +75,11 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Region("Spirit Temple Central Chamber", SCENE_SPIRIT_TEMPLE, {}, { areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Region("Spirit Temple Central Chamber", SCENE_SPIRIT_TEMPLE, {}, {
//Locations //Locations
LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) &&
(logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) || (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) ||
(logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) ||
(logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))),
LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) &&
(logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) || (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) ||
(logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) ||
(logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))),
@ -87,20 +87,19 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))), LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))),
LOCATION(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, (logic->HasExplosives() && logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_HOOKSHOT)) || LOCATION(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, (logic->HasExplosives() && logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_HOOKSHOT)) ||
(logic->CanUse(RG_BOOMERANG) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives()) || (logic->CanUse(RG_BOOMERANG) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives()) ||
(logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2))),
logic->CanUse(RG_BOOMERANG) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))))), LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) &&
LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) &&
ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->CanUse(RG_BOOMERANG) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->CanUse(RG_BOOMERANG) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) ||
(ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_BOOMERANG)) || (ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_BOOMERANG)) ||
(logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)))), (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)))),
LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_1, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_1, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)),
LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_2, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_2, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)),
LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)),
LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)),
LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)),
LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_4, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_4, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)),
LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_5, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_5, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)),
LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_OUTDOOR_HANDS, []{return logic->CanJumpslashExceptHammer() || logic->HasExplosives();}), Entrance(RR_SPIRIT_TEMPLE_OUTDOOR_HANDS, []{return logic->CanJumpslashExceptHammer() || logic->HasExplosives();}),

View file

@ -49,7 +49,7 @@ void RegionTable_Init_GerudoFortress() {
EventAccess(&logic->GtG_GateOpen, []{return (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET));}), EventAccess(&logic->GtG_GateOpen, []{return (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET));}),
}, {}, { }, {}, {
//Exits //Exits
Entrance(RR_GERUDO_TRAINING_GROUND_ENTRYWAY, []{return logic->GtG_GateOpen && (logic->IsAdult || ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}), Entrance(RR_GF_TO_GTG, []{return logic->GtG_GateOpen && (logic->IsAdult || ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}),
//Jail //Jail
Entrance(RR_GF_JAIL_WINDOW, []{return logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_GF_JAIL_WINDOW, []{return logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_GF_OUTSKIRTS, []{return true;}), Entrance(RR_GF_OUTSKIRTS, []{return true;}),
@ -60,6 +60,17 @@ void RegionTable_Init_GerudoFortress() {
Entrance(RR_GF_HBA_RANGE, []{return logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), Entrance(RR_GF_HBA_RANGE, []{return logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}),
}); });
areaTable[RR_GF_TO_GTG] = Region("GF to GTG", SCENE_GERUDOS_FORTRESS, {}, {}, {
Entrance(RR_GERUDO_TRAINING_GROUND_ENTRYWAY, []{return true;}),
});
// Split out to handle adult being immediately captured without card
areaTable[RR_GF_EXITING_GTG] = Region("GF Exiting GTG", SCENE_GERUDOS_FORTRESS, {}, {}, {
Entrance(RR_GF_OUTSIDE_GTG, []{return logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}),
Entrance(RR_GF_JAIL_WINDOW, []{return logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_GF_OUTSKIRTS, []{return true;}),
});
#pragma endregion #pragma endregion
#pragma region Rooftops #pragma region Rooftops
@ -123,6 +134,7 @@ void RegionTable_Init_GerudoFortress() {
Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true;}), Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true;}),
Entrance(RR_GF_SLOPED_ROOF, []{return logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_GF_SLOPED_ROOF, []{return logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return true /* logic->CanClimb() */;}), Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return true /* logic->CanClimb() */;}),
Entrance(RR_GF_TO_GTG, []{return logic->IsAdult && ctx->GetTrickOption(RT_GF_LEDGE_CLIP_INTO_GTG).Get();}),
}); });
areaTable[RR_GF_TOP_OF_UPPER_VINES] = Region("GF Top of Upper Vines", SCENE_GERUDOS_FORTRESS, {}, { areaTable[RR_GF_TOP_OF_UPPER_VINES] = Region("GF Top of Upper Vines", SCENE_GERUDOS_FORTRESS, {}, {

View file

@ -63,7 +63,7 @@ void RegionTable_Init_GoronCity() {
EventAccess(&logic->GCWoodsWarpOpen, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}), EventAccess(&logic->GCWoodsWarpOpen, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}),
}, {}, { }, {}, {
//Exits //Exits
Entrance(RR_GORON_CITY, []{return logic->CanLeaveForest() && logic->GCWoodsWarpOpen;}), Entrance(RR_GORON_CITY, []{return logic->GCWoodsWarpOpen;}),
Entrance(RR_THE_LOST_WOODS, []{return true;}), Entrance(RR_THE_LOST_WOODS, []{return true;}),
}); });

View file

@ -10,6 +10,7 @@ void RegionTable_Init_Graveyard() {
EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}), EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}),
EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}),
EventAccess(&logic->BugRock, []{return true;}), EventAccess(&logic->BugRock, []{return true;}),
EventAccess(&logic->BorrowBunnyHood, []{return logic->IsChild && logic->AtDay && logic->BorrowSpookyMask && logic->HasItem(RG_CHILD_WALLET);}),
}, { }, {
//Locations //Locations
LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()) || (ctx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))), LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()) || (ctx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))),

View file

@ -8,6 +8,7 @@ void RegionTable_Init_HyruleField() {
areaTable[RR_HYRULE_FIELD] = Region("Hyrule Field", SCENE_HYRULE_FIELD, { areaTable[RR_HYRULE_FIELD] = Region("Hyrule Field", SCENE_HYRULE_FIELD, {
//Events //Events
EventAccess(&logic->BigPoeKill, []{return logic->HasBottle() && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_EPONA) || ctx->GetTrickOption(RT_HF_BIG_POE_WITHOUT_EPONA));}), EventAccess(&logic->BigPoeKill, []{return logic->HasBottle() && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_EPONA) || ctx->GetTrickOption(RT_HF_BIG_POE_WITHOUT_EPONA));}),
EventAccess(&logic->BorrowRightMasks, []{return logic->IsChild && logic->BorrowBunnyHood && logic->HasItem(RG_KOKIRI_EMERALD) && logic->HasItem(RG_GORON_RUBY) && logic->HasItem(RG_ZORA_SAPPHIRE) && logic->HasItem(RG_CHILD_WALLET);}),
}, { }, {
//Locations //Locations
LOCATION(RC_HF_OCARINA_OF_TIME_ITEM, logic->IsChild && logic->StoneCount() == 3 && logic->HasItem(RG_BRONZE_SCALE)), LOCATION(RC_HF_OCARINA_OF_TIME_ITEM, logic->IsChild && logic->StoneCount() == 3 && logic->HasItem(RG_BRONZE_SCALE)),

View file

@ -10,6 +10,8 @@ void RegionTable_Init_Kakariko() {
EventAccess(&logic->BugRock, []{return true;}), EventAccess(&logic->BugRock, []{return true;}),
//Open Gate setting is applied in RR_ROOT //Open Gate setting is applied in RR_ROOT
EventAccess(&logic->KakarikoVillageGateOpen, []{return logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER);}), EventAccess(&logic->KakarikoVillageGateOpen, []{return logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER);}),
//Needs wallet to be able to get another mask after selling Keaton
EventAccess(&logic->BorrowSkullMask, []{return logic->IsChild && logic->CanBorrowMasks && logic->HasItem(RG_CHILD_WALLET);}),
}, { }, {
//Locations //Locations
LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->HasItem(RG_FOREST_MEDALLION) && logic->HasItem(RG_FIRE_MEDALLION) && logic->HasItem(RG_WATER_MEDALLION)), LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->HasItem(RG_FOREST_MEDALLION) && logic->HasItem(RG_FIRE_MEDALLION) && logic->HasItem(RG_WATER_MEDALLION)),

View file

@ -13,7 +13,7 @@ void RegionTable_Init_KokiriForest() {
}, { }, {
//Locations //Locations
LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild), LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild),
LOCATION(RC_KF_GS_KNOW_IT_ALL_HOUSE, logic->IsChild && logic->CanAttack() && (/*TODO: HasNightStart ||*/ logic->CanLeaveForest() || logic->CanUse(RG_SUNS_SONG)) && logic->CanGetNightTimeGS()), LOCATION(RC_KF_GS_KNOW_IT_ALL_HOUSE, logic->IsChild && logic->CanAttack() && logic->CanGetNightTimeGS()),
LOCATION(RC_KF_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanAttack()), LOCATION(RC_KF_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanAttack()),
LOCATION(RC_KF_GS_HOUSE_OF_TWINS, logic->IsAdult && (logic->HookshotOrBoomerang() || (ctx->GetTrickOption(RT_KF_ADULT_GS) && logic->CanUse(RG_HOVER_BOOTS))) && logic->CanGetNightTimeGS()), LOCATION(RC_KF_GS_HOUSE_OF_TWINS, logic->IsAdult && (logic->HookshotOrBoomerang() || (ctx->GetTrickOption(RT_KF_ADULT_GS) && logic->CanUse(RG_HOVER_BOOTS))) && logic->CanGetNightTimeGS()),
LOCATION(RC_KF_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_KF_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)),

View file

@ -15,6 +15,7 @@ void RegionTable_Init_LostWoods() {
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}),
EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}),
EventAccess(&logic->BugShrub, []{return logic->IsChild && logic->CanCutShrubs();}), EventAccess(&logic->BugShrub, []{return logic->IsChild && logic->CanCutShrubs();}),
EventAccess(&logic->BorrowSpookyMask, []{return logic->IsChild && logic->BorrowSkullMask && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET);}),
}, { }, {
//Locations //Locations
LOCATION(RC_LW_SKULL_KID, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)), LOCATION(RC_LW_SKULL_KID, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)),
@ -56,8 +57,8 @@ void RegionTable_Init_LostWoods() {
//Exits //Exits
Entrance(RR_LW_FOREST_EXIT, []{return true;}), Entrance(RR_LW_FOREST_EXIT, []{return true;}),
Entrance(RR_GC_WOODS_WARP, []{return true;}), Entrance(RR_GC_WOODS_WARP, []{return true;}),
Entrance(RR_LW_BRIDGE, []{return logic->CanLeaveForest() && ((logic->IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT));}), Entrance(RR_LW_BRIDGE, []{return (logic->IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT);}),
Entrance(RR_ZR_FROM_SHORTCUT, []{return logic->CanLeaveForest() && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LOST_WOOD_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash()));}), Entrance(RR_ZR_FROM_SHORTCUT, []{return logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LOST_WOOD_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash());}),
Entrance(RR_LW_BEYOND_MIDO, []{return logic->IsChild || logic->CanUse(RG_SARIAS_SONG) || ctx->GetTrickOption(RT_LW_MIDO_BACKFLIP);}), Entrance(RR_LW_BEYOND_MIDO, []{return logic->IsChild || logic->CanUse(RG_SARIAS_SONG) || ctx->GetTrickOption(RT_LW_MIDO_BACKFLIP);}),
Entrance(RR_LW_NEAR_SHORTCUTS_GROTTO, []{return Here(RR_THE_LOST_WOODS, []{return logic->BlastOrSmash();});}), Entrance(RR_LW_NEAR_SHORTCUTS_GROTTO, []{return Here(RR_THE_LOST_WOODS, []{return logic->BlastOrSmash();});}),
}); });
@ -110,8 +111,8 @@ void RegionTable_Init_LostWoods() {
areaTable[RR_DEKU_THEATER] = Region("Deku Theater", SCENE_GROTTOS, {}, { areaTable[RR_DEKU_THEATER] = Region("Deku Theater", SCENE_GROTTOS, {}, {
//Locations //Locations
LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->IsChild && logic->SkullMask), LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->IsChild && logic->BorrowSkullMask),
LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->IsChild && logic->MaskOfTruth), LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->IsChild && logic->BorrowRightMasks),
}, { }, {
//Exits //Exits
Entrance(RR_LW_BEYOND_MIDO, []{return true;}), Entrance(RR_LW_BEYOND_MIDO, []{return true;}),

View file

@ -138,8 +138,14 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_MASK_SHOP] = Region("Market Mask Shop", SCENE_HAPPY_MASK_SHOP, { areaTable[RR_MARKET_MASK_SHOP] = Region("Market Mask Shop", SCENE_HAPPY_MASK_SHOP, {
//Events //Events
EventAccess(&logic->SkullMask, []{return logic->HasItem(RG_ZELDAS_LETTER) && (ctx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE));}), //RANDOTODO Complete mask quest does not need this location, so should be tied to link's pocket //Currently, mask swap in menu doesn't need access to the mask shop
EventAccess(&logic->MaskOfTruth, []{return logic->SkullMask && (ctx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && logic->CanUse(RG_SARIAS_SONG) && RegionTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && logic->StoneCount() == 3));}), //If it is forced on/a setting, a copy of these events should be added to root
//it also doesn't need you to open kak gate, but that might be best treated as a bug
EventAccess(&logic->CanBorrowMasks, []{return logic->HasItem(RG_ZELDAS_LETTER) && logic->KakarikoVillageGateOpen;}),
EventAccess(&logic->BorrowSkullMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}),
EventAccess(&logic->BorrowSpookyMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}),
EventAccess(&logic->BorrowBunnyHood, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}),
EventAccess(&logic->BorrowRightMasks, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}),
}, { }, {
//Locations //Locations
LOCATION(RC_MASK_SHOP_HINT, true), LOCATION(RC_MASK_SHOP_HINT, true),

View file

@ -31,7 +31,7 @@ void RegionTable_Init_ZorasFountain() {
//child can break the brown rock without lifting the silver rock and it stays gone for adult, but it's not intuitive and there's no reasonable case where it matters. //child can break the brown rock without lifting the silver rock and it stays gone for adult, but it's not intuitive and there's no reasonable case where it matters.
Entrance(RR_ZF_HIDDEN_CAVE, []{return logic->CanUse(RG_SILVER_GAUNTLETS) && logic->BlastOrSmash();}), Entrance(RR_ZF_HIDDEN_CAVE, []{return logic->CanUse(RG_SILVER_GAUNTLETS) && logic->BlastOrSmash();}),
Entrance(RR_ZF_ROCK, []{return logic->IsAdult && logic->CanUse(RG_SCARECROW);}), Entrance(RR_ZF_ROCK, []{return logic->IsAdult && logic->CanUse(RG_SCARECROW);}),
Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, []{return (logic->IsChild && logic->CanUse(RG_BOTTLE_WITH_FISH));}), Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, []{return logic->IsChild && (ctx->GetOption(RSK_JABU_OPEN).Is(RO_JABU_OPEN) || logic->CanUse(RG_BOTTLE_WITH_FISH));}),
Entrance(RR_ZF_GREAT_FAIRY_FOUNTAIN, []{return logic->HasExplosives() || (ctx->GetTrickOption(RT_ZF_GREAT_FAIRY_WITHOUT_EXPLOSIVES) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_SILVER_GAUNTLETS));}), Entrance(RR_ZF_GREAT_FAIRY_FOUNTAIN, []{return logic->HasExplosives() || (ctx->GetTrickOption(RT_ZF_GREAT_FAIRY_WITHOUT_EXPLOSIVES) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_SILVER_GAUNTLETS));}),
}); });
@ -41,7 +41,7 @@ void RegionTable_Init_ZorasFountain() {
}, { }, {
//Exits //Exits
//This hover is pretty tight, come at it with momentum and aim for the small corner polygon of the big iceburg while spamming roll //This hover is pretty tight, come at it with momentum and aim for the small corner polygon of the big iceburg while spamming roll
Entrance(RR_ZORAS_FOUNTAIN, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}), Entrance(RR_ZORAS_FOUNTAIN, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_ZF_LAKEBED, []{return logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_ZF_LAKEBED, []{return logic->CanUse(RG_IRON_BOOTS);}),
Entrance(RR_ZF_LEDGE, []{return true;}), Entrance(RR_ZF_LEDGE, []{return true;}),
}); });

View file

@ -1177,11 +1177,6 @@ bool Logic::CanStunDeku() {
return CanAttack() || CanUse(RG_NUTS) || CanReflectNuts(); return CanAttack() || CanUse(RG_NUTS) || CanReflectNuts();
} }
bool Logic::CanLeaveForest() {
return ctx->GetOption(RSK_FOREST).IsNot(RO_CLOSED_FOREST_ON) || IsAdult || DekuTreeClear ||
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES);
}
bool Logic::CallGossipFairyExceptSuns() { bool Logic::CallGossipFairyExceptSuns() {
return CanUse(RG_ZELDAS_LULLABY) || CanUse(RG_EPONAS_SONG) || CanUse(RG_SONG_OF_TIME); return CanUse(RG_ZELDAS_LULLABY) || CanUse(RG_EPONAS_SONG) || CanUse(RG_SONG_OF_TIME);
} }
@ -2350,9 +2345,12 @@ void Logic::Reset(bool resetSaveContext /*= true*/) {
// AmmoCanDrop = /*AmmoDrops.IsNot(AMMODROPS_NONE)*/ false; TODO: AmmoDrop setting // AmmoCanDrop = /*AmmoDrops.IsNot(AMMODROPS_NONE)*/ false; TODO: AmmoDrop setting
// Child item logic // Mask quest
SkullMask = false; CanBorrowMasks = false;
MaskOfTruth = false; BorrowSkullMask = false;
BorrowSpookyMask = false;
BorrowBunnyHood = false;
BorrowRightMasks = false;
// Adult logic // Adult logic
FreedEpona = false; FreedEpona = false;

View file

@ -30,9 +30,12 @@ class Logic {
public: public:
bool noVariable = false; bool noVariable = false;
// Child item logic // Mask Quest
bool SkullMask = false; bool CanBorrowMasks = false;
bool MaskOfTruth = false; bool BorrowSkullMask = false;
bool BorrowSpookyMask = false;
bool BorrowBunnyHood = false;
bool BorrowRightMasks = false;
// Adult logic // Adult logic
bool FreedEpona = false; bool FreedEpona = false;
@ -228,7 +231,6 @@ class Logic {
bool CanReflectNuts(); bool CanReflectNuts();
bool CanCutShrubs(); bool CanCutShrubs();
bool CanStunDeku(); bool CanStunDeku();
bool CanLeaveForest();
bool CallGossipFairy(); bool CallGossipFairy();
bool CallGossipFairyExceptSuns(); bool CallGossipFairyExceptSuns();
uint8_t EffectiveHealth(); uint8_t EffectiveHealth();

View file

@ -42,6 +42,8 @@ void Settings::CreateOptionDescriptions() {
"\n" "\n"
"Open - Sleeping Waterfall is always open. " "Open - Sleeping Waterfall is always open. "
"Link may always enter Zora's Domain."; "Link may always enter Zora's Domain.";
mOptionDescriptions[RSK_JABU_OPEN] = "Closed - A fish is required to open Jabu-Jabu's mouth.\n\n"
"Open - Jabu-Jabu's mouth opens without the need for a fish.";
mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS] = mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS] =
"Add locks to all wooden overworld doors, requiring specific small keys to open them"; "Add locks to all wooden overworld doors, requiring specific small keys to open them";
mOptionDescriptions[RSK_STARTING_AGE] = mOptionDescriptions[RSK_STARTING_AGE] =

View file

@ -472,26 +472,72 @@ std::unordered_map<s16, s16> getItemIdToItemId = {
#pragma GCC optimize("O0") #pragma GCC optimize("O0")
#endif #endif
bool Randomizer::SpoilerFileExists(const char* spoilerFileName) { bool Randomizer::SpoilerFileExists(const char* spoilerFileName) {
if (strcmp(spoilerFileName, "") != 0) { static std::unordered_map<std::string, bool> existsCache;
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName)); static std::unordered_map<std::string, std::filesystem::file_time_type> lastModifiedCache;
if (strcmp(spoilerFileName, "") == 0) {
return false;
}
std::string sanitizedFileName = SohUtils::Sanitize(spoilerFileName);
try {
// Check if file exists and get last modified time
std::filesystem::path filePath(sanitizedFileName);
if (!std::filesystem::exists(filePath)) {
// Cache and return false if file doesn't exist
existsCache[sanitizedFileName] = false;
lastModifiedCache.erase(sanitizedFileName);
return false;
}
auto currentLastModified = std::filesystem::last_write_time(filePath);
// Check cache first
auto existsCacheIt = existsCache.find(sanitizedFileName);
auto lastModifiedCacheIt = lastModifiedCache.find(sanitizedFileName);
// If we have a valid cache entry and the file hasn't been modified
if (existsCacheIt != existsCache.end() && lastModifiedCacheIt != lastModifiedCache.end() &&
lastModifiedCacheIt->second == currentLastModified) {
return existsCacheIt->second;
}
// Cache miss or file modified - need to check contents
std::ifstream spoilerFileStream(sanitizedFileName);
if (spoilerFileStream) { if (spoilerFileStream) {
nlohmann::json contents; nlohmann::json contents;
spoilerFileStream >> contents; spoilerFileStream >> contents;
spoilerFileStream.close(); spoilerFileStream.close();
if (contents.contains("version") &&
strcmp(std::string(contents["version"]).c_str(), (char*)gBuildVersion) == 0) { bool isValid = contents.contains("version") &&
return true; strcmp(std::string(contents["version"]).c_str(), (char*)gBuildVersion) == 0;
} else {
if (!isValid) {
SohGui::RegisterPopup( SohGui::RegisterPopup(
"Old Spoiler Version", "Old Spoiler Version",
"The spoiler file located at\n" + std::string(spoilerFileName) + "The spoiler file located at\n" + std::string(spoilerFileName) +
"\nwas made by a version that doesn't match the currently running version.\n" + "\nwas made by a version that doesn't match the currently running version.\n" +
"Loading for this file has been cancelled."); "Loading for this file has been cancelled.");
} }
}
// Update cache
existsCache[sanitizedFileName] = isValid;
lastModifiedCache[sanitizedFileName] = currentLastModified;
return isValid;
} }
// File couldn't be opened
existsCache[sanitizedFileName] = false;
lastModifiedCache.erase(sanitizedFileName);
return false; return false;
} catch (const std::filesystem::filesystem_error&) {
// Handle filesystem errors by invalidating cache
existsCache[sanitizedFileName] = false;
lastModifiedCache.erase(sanitizedFileName);
return false;
}
} }
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma optimize("", on) #pragma optimize("", on)
@ -3713,7 +3759,7 @@ std::thread randoThread;
void GenerateRandomizerImgui(std::string seed = "") { void GenerateRandomizerImgui(std::string seed = "") {
CVarSetInteger(CVAR_GENERAL("RandoGenerating"), 1); CVarSetInteger(CVAR_GENERAL("RandoGenerating"), 1);
CVarSave(); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
// RANDOTODO proper UI for selecting if a spoiler loaded should be used for settings // RANDOTODO proper UI for selecting if a spoiler loaded should be used for settings
Rando::Settings::GetInstance()->SetAllToContext(); Rando::Settings::GetInstance()->SetAllToContext();

View file

@ -401,6 +401,8 @@ typedef enum {
RR_GF_OUTSKIRTS, RR_GF_OUTSKIRTS,
RR_GF_NEAR_GROTTO, RR_GF_NEAR_GROTTO,
RR_GF_OUTSIDE_GTG, RR_GF_OUTSIDE_GTG,
RR_GF_TO_GTG,
RR_GF_EXITING_GTG,
RR_GF_ABOVE_GTG, RR_GF_ABOVE_GTG,
RR_GF_BOTTOM_OF_LOWER_VINES, RR_GF_BOTTOM_OF_LOWER_VINES,
RR_GF_TOP_OF_LOWER_VINES, RR_GF_TOP_OF_LOWER_VINES,
@ -3559,6 +3561,7 @@ typedef enum {
RT_PASS_GUARDS_WITH_NOTHING, RT_PASS_GUARDS_WITH_NOTHING,
RT_GF_JUMP, RT_GF_JUMP,
RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON, RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON,
RT_GF_LEDGE_CLIP_INTO_GTG,
RT_HW_BUNNY_CROSSING, RT_HW_BUNNY_CROSSING,
RT_HW_CROSSING, RT_HW_CROSSING,
RT_LENS_HW, RT_LENS_HW,
@ -5421,7 +5424,9 @@ typedef enum {
RHT_SKULLS_HINT, RHT_SKULLS_HINT,
RHT_MASK_SHOP_HINT, RHT_MASK_SHOP_HINT,
// Shuffle Pots // Shuffle Pots
RHT_POT_KOKIRI_FOREST, RHT_POT_LINKS_HOUSE,
RHT_POT_TWINS_HOUSE,
RHT_POT_KNOW_IT_ALL,
RHT_TH_BREAK_ROOM_FRONT_POT, RHT_TH_BREAK_ROOM_FRONT_POT,
RHT_TH_BREAK_ROOM_BACK_POT, RHT_TH_BREAK_ROOM_BACK_POT,
RHT_TH_KITCHEN_POT_1, RHT_TH_KITCHEN_POT_1,
@ -5439,16 +5444,19 @@ typedef enum {
RHT_TH_LEFT_MIDDLE_JAILED_POT, RHT_TH_LEFT_MIDDLE_JAILED_POT,
RHT_TH_LEFTMOST_JAILED_POT, RHT_TH_LEFTMOST_JAILED_POT,
RHT_POT_WASTELAND, RHT_POT_WASTELAND,
RHT_POT_MARKET, RHT_POT_GUARD_HOUSE,
RHT_POT_POE_SHOP,
RHT_POT_ALLEY_HOUSE,
RHT_POT_KAKARIKO, RHT_POT_KAKARIKO,
RHT_POT_GRAVEYARD, RHT_POT_DAMPE,
RHT_POT_GORON_CITY, RHT_POT_GORON_CITY,
RHT_POT_DEATH_MOUNTAIN_CRATER, RHT_POT_DEATH_MOUNTAIN_CRATER,
RHT_POT_ZORAS_DOMAIN, RHT_POT_ZORAS_DOMAIN,
RHT_POT_ZORAS_FOUNTAIN, RHT_POT_ZORAS_FOUNTAIN,
RHT_POT_LON_LON_RANCH, RHT_POT_LON_LON_RANCH,
RHT_POT_HYRULE_FIELD, RHT_POT_TALONS_HOUSE,
RHT_POT_HYRULE_CASTLE, RHT_POT_WEB_GROTTO,
RHT_POT_MUD_WALL_GROTTO,
RHT_POT_DODONGOS_CAVERN, RHT_POT_DODONGOS_CAVERN,
RHT_POT_JABU_JABUS_BELLY, RHT_POT_JABU_JABUS_BELLY,
RHT_POT_FOREST_TEMPLE, RHT_POT_FOREST_TEMPLE,
@ -5754,6 +5762,7 @@ typedef enum {
RSK_DOOR_OF_TIME, RSK_DOOR_OF_TIME,
RSK_ZORAS_FOUNTAIN, RSK_ZORAS_FOUNTAIN,
RSK_SLEEPING_WATERFALL, RSK_SLEEPING_WATERFALL,
RSK_JABU_OPEN,
RSK_STARTING_AGE, RSK_STARTING_AGE,
RSK_SELECTED_STARTING_AGE, RSK_SELECTED_STARTING_AGE,
RSK_GERUDO_FORTRESS, RSK_GERUDO_FORTRESS,
@ -6003,6 +6012,12 @@ typedef enum {
RO_WATERFALL_OPEN, RO_WATERFALL_OPEN,
} RandoOptionSleepingWaterfall; } RandoOptionSleepingWaterfall;
// Jabu-Jabu settings (closed, open)
typedef enum {
RO_JABU_CLOSED,
RO_JABU_OPEN,
} RandoOptionJabu;
// Starting Age settings (child, adult, random) // Starting Age settings (child, adult, random)
typedef enum { typedef enum {
RO_AGE_CHILD, RO_AGE_CHILD,

View file

@ -500,6 +500,9 @@ void SetShopSeen(uint32_t sceneNum, bool prices) {
} }
void CheckTrackerLoadGame(int32_t fileNum) { void CheckTrackerLoadGame(int32_t fileNum) {
if (IS_BOSS_RUSH) {
return;
}
LoadSettings(); LoadSettings();
TrySetAreas(); TrySetAreas();
for (auto& entry : Rando::StaticData::GetLocationTable()) { for (auto& entry : Rando::StaticData::GetLocationTable()) {
@ -592,7 +595,7 @@ void CheckTrackerLoadGame(int32_t fileNum) {
Rando::Context::GetInstance()->GetEntranceShuffler()->ApplyEntranceOverrides(); Rando::Context::GetInstance()->GetEntranceShuffler()->ApplyEntranceOverrides();
} }
RecalculateAvailableChecks(); recalculateAvailable = true;
} }
void CheckTrackerShopSlotChange(uint8_t cursorSlot, int16_t basePrice) { void CheckTrackerShopSlotChange(uint8_t cursorSlot, int16_t basePrice) {
@ -1005,6 +1008,11 @@ void CheckTrackerWindow::DrawElement() {
return; return;
} }
if (recalculateAvailable) {
recalculateAvailable = false;
RecalculateAvailableChecks();
}
SceneID sceneId = SCENE_ID_MAX; SceneID sceneId = SCENE_ID_MAX;
if (gPlayState != nullptr) { if (gPlayState != nullptr) {
sceneId = (SceneID)gPlayState->sceneNum; sceneId = (SceneID)gPlayState->sceneNum;
@ -1603,10 +1611,11 @@ bool IsCheckShuffled(RandomizerCheck rc) {
bool IsVisibleInCheckTracker(RandomizerCheck rc) { bool IsVisibleInCheckTracker(RandomizerCheck rc) {
auto loc = Rando::StaticData::GetLocation(rc); auto loc = Rando::StaticData::GetLocation(rc);
if (IS_RANDO) { if (IS_RANDO) {
return IsCheckShuffled(rc) || return !Rando::Context::GetInstance()->GetItemLocation(rc)->IsExcluded() &&
(IsCheckShuffled(rc) ||
(alwaysShowGS && loc->GetRCType() == RCTYPE_SKULL_TOKEN && (alwaysShowGS && loc->GetRCType() == RCTYPE_SKULL_TOKEN &&
OTRGlobals::Instance->gRandoContext->IsQuestOfLocationActive(rc)) || OTRGlobals::Instance->gRandoContext->IsQuestOfLocationActive(rc)) ||
(loc->GetRCType() == RCTYPE_SHOP && showShops && !hideShopUnshuffledChecks); (loc->GetRCType() == RCTYPE_SHOP && showShops && !hideShopUnshuffledChecks));
} else { } else {
return loc->IsVanillaCompletion() && return loc->IsVanillaCompletion() &&
(!loc->IsDungeon() || (loc->IsDungeon() && loc->GetQuest() == gSaveContext.ship.quest.id)); (!loc->IsDungeon() || (loc->IsDungeon() && loc->GetQuest() == gSaveContext.ship.quest.id));
@ -1994,7 +2003,7 @@ void ImGuiDrawTwoColorPickerSection(const char* text, const char* cvarMainName,
} }
void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) { void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) {
if (!enableAvailableChecks) { if (!enableAvailableChecks || !GameInteractor::IsSaveLoaded()) {
return; return;
} }
@ -2066,10 +2075,6 @@ static std::unordered_map<int32_t, const char*> buttonStrings = {
}; };
void CheckTrackerSettingsWindow::DrawElement() { void CheckTrackerSettingsWindow::DrawElement() {
if (recalculateAvailable) {
recalculateAvailable = false;
RecalculateAvailableChecks();
}
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f }); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f });
if (ImGui::BeginTable("CheckTrackerSettingsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { if (ImGui::BeginTable("CheckTrackerSettingsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) {
ImGui::TableSetupColumn("General settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::TableSetupColumn("General settings", ImGuiTableColumnFlags_WidthStretch, 200.0f);
@ -2150,11 +2155,8 @@ void CheckTrackerSettingsWindow::DrawElement() {
"with your current progress.") "with your current progress.")
.Color(THEME_COLOR))) { .Color(THEME_COLOR))) {
enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0); enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0);
if (GameInteractor::IsSaveLoaded(true)) {
RecalculateAvailableChecks(); RecalculateAvailableChecks();
} }
}
ImGui::EndDisabled(); ImGui::EndDisabled();
// Filtering settings // Filtering settings

View file

@ -1091,6 +1091,8 @@ DEFINE_RAND_INF(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5)
DEFINE_RAND_INF(RAND_INF_TH_ITEM_FROM_LEADER_OF_FORTRESS) DEFINE_RAND_INF(RAND_INF_TH_ITEM_FROM_LEADER_OF_FORTRESS)
DEFINE_RAND_INF(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN) DEFINE_RAND_INF(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN)
DEFINE_RAND_INF(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON)
DEFINE_RAND_INF(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED)
DEFINE_RAND_INF(RAND_INF_ZELDAS_LETTER) DEFINE_RAND_INF(RAND_INF_ZELDAS_LETTER)
DEFINE_RAND_INF(RAND_INF_WEIRD_EGG) DEFINE_RAND_INF(RAND_INF_WEIRD_EGG)

View file

@ -680,7 +680,7 @@ void DrawQuest(ItemTrackerItem item) {
bool hasQuestItem = HasQuestItem(item); bool hasQuestItem = HasQuestItem(item);
float iconSize = static_cast<float>(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36)); float iconSize = static_cast<float>(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36));
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( ImGui::ImageWithBg(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded), hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
@ -1215,7 +1215,7 @@ void DrawItemsInACircle(std::vector<ItemTrackerItem> items) {
float radius = (iconSize + iconSpacing) * 2.0f; float radius = (iconSize + iconSpacing) * 2.0f;
for (int i = 0; i < items.size(); i++) { for (int i = 0; i < items.size(); i++) {
float angle = static_cast<float>(i / items.size() * 2.0f * M_PI); float angle = static_cast<float>(i) / items.size() * 2.0f * M_PIf;
float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f; float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f;
float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f; float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f;
ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36) - 8) / 2.0f, y + 4)); ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36) - 8) / 2.0f, y + 4));

View file

@ -358,17 +358,6 @@ extern "C" void Randomizer_InitSaveFile() {
gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15); gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15);
} }
// Now handled on the fly.
// int openForest = Randomizer_GetSettingValue(RSK_FOREST);
// switch (openForest) {
// case RO_CLOSED_FOREST_OFF:
// Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
// // Fallthrough
// case RO_CLOSED_FOREST_DEKU_ONLY:
// Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
// break;
// }
int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME);
switch (doorOfTime) { switch (doorOfTime) {
case RO_DOOROFTIME_OPEN: case RO_DOOROFTIME_OPEN:

View file

@ -120,6 +120,7 @@ void Settings::CreateOptions() {
OPT_U8(RSK_DOOR_OF_TIME, "Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DoorOfTime"), mOptionDescriptions[RSK_DOOR_OF_TIME], WidgetType::Combobox); OPT_U8(RSK_DOOR_OF_TIME, "Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DoorOfTime"), mOptionDescriptions[RSK_DOOR_OF_TIME], WidgetType::Combobox);
OPT_U8(RSK_ZORAS_FOUNTAIN, "Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ZorasFountain"), mOptionDescriptions[RSK_ZORAS_FOUNTAIN]); OPT_U8(RSK_ZORAS_FOUNTAIN, "Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ZorasFountain"), mOptionDescriptions[RSK_ZORAS_FOUNTAIN]);
OPT_U8(RSK_SLEEPING_WATERFALL, "Sleeping Waterfall", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), mOptionDescriptions[RSK_SLEEPING_WATERFALL]); OPT_U8(RSK_SLEEPING_WATERFALL, "Sleeping Waterfall", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), mOptionDescriptions[RSK_SLEEPING_WATERFALL]);
OPT_U8(RSK_JABU_OPEN, "Jabu-Jabu", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("JabuJabu"), mOptionDescriptions[RSK_JABU_OPEN]);
OPT_BOOL(RSK_LOCK_OVERWORLD_DOORS, "Lock Overworld Doors", CVAR_RANDOMIZER_SETTING("LockOverworldDoors"), mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS]); OPT_BOOL(RSK_LOCK_OVERWORLD_DOORS, "Lock Overworld Doors", CVAR_RANDOMIZER_SETTING("LockOverworldDoors"), mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS]);
OPT_U8(RSK_GERUDO_FORTRESS, "Fortress Carpenters", {"Normal", "Fast", "Free"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FortressCarpenters"), mOptionDescriptions[RSK_GERUDO_FORTRESS]); OPT_U8(RSK_GERUDO_FORTRESS, "Fortress Carpenters", {"Normal", "Fast", "Free"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FortressCarpenters"), mOptionDescriptions[RSK_GERUDO_FORTRESS]);
OPT_U8(RSK_RAINBOW_BRIDGE, "Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RainbowBridge"), mOptionDescriptions[RSK_RAINBOW_BRIDGE], WidgetType::Combobox, RO_BRIDGE_VANILLA, false, IMFLAG_NONE); OPT_U8(RSK_RAINBOW_BRIDGE, "Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RainbowBridge"), mOptionDescriptions[RSK_RAINBOW_BRIDGE], WidgetType::Combobox, RO_BRIDGE_VANILLA, false, IMFLAG_NONE);
@ -590,6 +591,9 @@ void Settings::CreateOptions() {
OPT_TRICK(RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE }, OPT_TRICK(RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE },
"Gerudo\'s Fortress Warriors with Difficult Weapons", "Gerudo\'s Fortress Warriors with Difficult Weapons",
"Warriors can be defeated with Slingshot or Bombchus."); "Warriors can be defeated with Slingshot or Bombchus.");
OPT_TRICK(RT_GF_LEDGE_CLIP_INTO_GTG, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH },
"Ledge Clip into Training Ground",
"Adult Link can use a ledge clip to enter Gerudo Training Ground without Gerudo Card.");
// disabled for now, can't check for being able to use bunny hood & bunny hood speedup is currently completely // disabled for now, can't check for being able to use bunny hood & bunny hood speedup is currently completely
// decoupled from rando OPT_TRICK(RT_HW_BUNNY_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::NOVICE}, // decoupled from rando OPT_TRICK(RT_HW_BUNNY_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::NOVICE},
// "Wasteland Crossing with Bunny Hood", "You can beat the quicksand by using the increased speed of the Bunny Hood. // "Wasteland Crossing with Bunny Hood", "You can beat the quicksand by using the increased speed of the Bunny Hood.
@ -1173,6 +1177,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_DOOR_OF_TIME], &mOptions[RSK_DOOR_OF_TIME],
&mOptions[RSK_ZORAS_FOUNTAIN], &mOptions[RSK_ZORAS_FOUNTAIN],
&mOptions[RSK_SLEEPING_WATERFALL], &mOptions[RSK_SLEEPING_WATERFALL],
&mOptions[RSK_JABU_OPEN],
&mOptions[RSK_LOCK_OVERWORLD_DOORS], &mOptions[RSK_LOCK_OVERWORLD_DOORS],
}, },
WidgetContainerType::COLUMN); WidgetContainerType::COLUMN);
@ -1427,6 +1432,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_DOOR_OF_TIME], &mOptions[RSK_DOOR_OF_TIME],
&mOptions[RSK_ZORAS_FOUNTAIN], &mOptions[RSK_ZORAS_FOUNTAIN],
&mOptions[RSK_SLEEPING_WATERFALL], &mOptions[RSK_SLEEPING_WATERFALL],
&mOptions[RSK_JABU_OPEN],
&mOptions[RSK_LOCK_OVERWORLD_DOORS], &mOptions[RSK_LOCK_OVERWORLD_DOORS],
&mOptions[RSK_GERUDO_FORTRESS], &mOptions[RSK_GERUDO_FORTRESS],
&mOptions[RSK_RAINBOW_BRIDGE], &mOptions[RSK_RAINBOW_BRIDGE],
@ -1826,10 +1832,9 @@ void Settings::UpdateOptionProperties() {
} else { } else {
mOptionGroups[RSG_AREA_ACCESS_IMGUI].Enable(); mOptionGroups[RSG_AREA_ACCESS_IMGUI].Enable();
// Starting Age - Disabled when Forest is set to Closed or under very specific conditions // Starting Age - Disabled when Forest is set to Closed or under very specific conditions
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ClosedForest"), RO_CLOSED_FOREST_ON) == RO_CLOSED_FOREST_ON || if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED &&
(CVarGetInteger(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED &&
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), RO_GENERIC_OFF) == CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), RO_GENERIC_OFF) ==
RO_GENERIC_OFF)) /* closed door of time with ocarina shuffle off */ { RO_GENERIC_OFF) /* closed door of time with ocarina shuffle off */ {
mOptions[RSK_STARTING_AGE].Disable( mOptions[RSK_STARTING_AGE].Disable(
"This option is disabled due to other options making the game unbeatable."); "This option is disabled due to other options making the game unbeatable.");
} else { } else {
@ -2526,8 +2531,7 @@ void Context::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocation
} }
// With certain access settings, the seed is only beatable if Starting Age is set to Child. // With certain access settings, the seed is only beatable if Starting Age is set to Child.
if (mOptions[RSK_FOREST].Is(RO_CLOSED_FOREST_ON) || if (mOptions[RSK_DOOR_OF_TIME].Is(RO_DOOROFTIME_CLOSED) && !mOptions[RSK_SHUFFLE_OCARINA]) {
(mOptions[RSK_DOOR_OF_TIME].Is(RO_DOOROFTIME_CLOSED) && !mOptions[RSK_SHUFFLE_OCARINA])) {
mOptions[RSK_STARTING_AGE].Set(RO_AGE_CHILD); mOptions[RSK_STARTING_AGE].Set(RO_AGE_CHILD);
} }
@ -2841,13 +2845,6 @@ void Context::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocation
mOptions[RSK_MIX_GROTTO_ENTRANCES].Set(RO_GENERIC_OFF); mOptions[RSK_MIX_GROTTO_ENTRANCES].Set(RO_GENERIC_OFF);
} }
if (mOptions[RSK_FOREST].Is(RO_CLOSED_FOREST_ON) &&
(mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES].Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL) ||
mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES] || mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS] ||
mOptions[RSK_DECOUPLED_ENTRANCES] || mOptions[RSK_MIXED_ENTRANCE_POOLS])) {
mOptions[RSK_FOREST].Set(RO_CLOSED_FOREST_DEKU_ONLY);
}
if (mOptions[RSK_STARTING_AGE].Is(RO_AGE_RANDOM)) { if (mOptions[RSK_STARTING_AGE].Is(RO_AGE_RANDOM)) {
if (const uint32_t choice = Random(0, 2); choice == 0) { if (const uint32_t choice = Random(0, 2); choice == 0) {
mOptions[RSK_SELECTED_STARTING_AGE].Set(RO_AGE_CHILD); mOptions[RSK_SELECTED_STARTING_AGE].Set(RO_AGE_CHILD);

View file

@ -31,7 +31,7 @@ class StaticData {
uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_,
uint16_t price_ = 0, CustomDrawFunc drawfunc_ = NULL); uint16_t price_ = 0, CustomDrawFunc drawfunc_ = NULL);
static void AddItem(RandomizerGet randomizerGet_, ItemType type_, int16_t getItemId_, LogicVal logicVal_, static void AddItem(RandomizerGet randomizerGet_, ItemType type_, int16_t getItemId_, LogicVal logicVal_,
RandomizerHintTextKey hintKey_, uint16_t price_ = 0); RandomizerHintTextKey hintKey_, GetItemCategory category_, uint16_t price_ = 0);
static void HintTable_Init(); static void HintTable_Init();
static void HintTable_Init_Item(); static void HintTable_Init_Item();
static void HintTable_Init_Exclude_Overworld(); static void HintTable_Init_Exclude_Overworld();

View file

@ -9,6 +9,7 @@ extern "C" {
#include "src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.h" #include "src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.h"
#include "src/overlays/actors/ovl_Elf_Msg/z_elf_msg.h" #include "src/overlays/actors/ovl_Elf_Msg/z_elf_msg.h"
#include "src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h" #include "src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h"
#include "src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.h"
#include "src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.h" #include "src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.h"
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" #include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
#include "src/overlays/actors/ovl_En_Owl/z_en_owl.h" #include "src/overlays/actors/ovl_En_Owl/z_en_owl.h"
@ -25,11 +26,13 @@ extern "C" {
#include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h" #include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h"
#include "src/overlays/actors/ovl_En_Tk/z_en_tk.h" #include "src/overlays/actors/ovl_En_Tk/z_en_tk.h"
#include "src/overlays/actors/ovl_En_Fu/z_en_fu.h" #include "src/overlays/actors/ovl_En_Fu/z_en_fu.h"
#include "src/overlays/actors/ovl_En_Jj/z_en_jj.h"
#include "src/overlays/actors/ovl_En_Daiku/z_en_daiku.h" #include "src/overlays/actors/ovl_En_Daiku/z_en_daiku.h"
#include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" #include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h"
#include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h" #include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h"
#include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h" #include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h"
#include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" #include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h"
#include "src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.h"
#include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h" #include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h"
#include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h" #include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h"
#include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h" #include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h"
@ -48,6 +51,10 @@ extern void EnGo2_CurledUp(EnGo2* enGo2, PlayState* play);
extern void EnRu2_SetEncounterSwitchFlag(EnRu2* enRu2, PlayState* play); extern void EnRu2_SetEncounterSwitchFlag(EnRu2* enRu2, PlayState* play);
extern void EnDaiku_EscapeSuccess(EnDaiku* enDaiku, PlayState* play); extern void EnDaiku_EscapeSuccess(EnDaiku* enDaiku, PlayState* play);
extern void EnJj_WaitToOpenMouth(EnJj* enJj, PlayState* play);
extern void EnJj_WaitForFish(EnJj* enJj, PlayState* play);
extern void EnJj_SetupAction(EnJj* enJj, EnJjActionFunc actionFunc);
} }
void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) { void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) {
@ -868,6 +875,8 @@ static uint32_t enMa1UpdateHook = 0;
static uint32_t enMa1KillHook = 0; static uint32_t enMa1KillHook = 0;
static uint32_t enFuUpdateHook = 0; static uint32_t enFuUpdateHook = 0;
static uint32_t enFuKillHook = 0; static uint32_t enFuKillHook = 0;
static uint32_t enJjUpdateHook = 0;
static uint32_t enJjKillHook = 0;
static uint32_t bgSpot02UpdateHook = 0; static uint32_t bgSpot02UpdateHook = 0;
static uint32_t bgSpot02KillHook = 0; static uint32_t bgSpot02KillHook = 0;
static uint32_t bgSpot03UpdateHook = 0; static uint32_t bgSpot03UpdateHook = 0;
@ -933,6 +942,39 @@ void TimeSaverOnActorInitHandler(void* actorRef) {
}); });
} }
if (actor->id == ACTOR_EN_JJ && !IS_RANDO) {
enJjUpdateHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* innerActorRef) mutable {
Actor* innerActor = static_cast<Actor*>(innerActorRef);
if (innerActor->id != ACTOR_EN_JJ || Flags_GetEventChkInf(EVENTCHKINF_OFFERED_FISH_TO_JABU_JABU)) {
return;
}
bool shouldOpen = IS_RANDO ? RAND_GET_OPTION(RSK_JABU_OPEN)
: CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipJabuJabuFish"), 0);
if (!shouldOpen) {
return;
}
EnJj* enJj = static_cast<EnJj*>(innerActorRef);
if (enJj->actionFunc == EnJj_WaitForFish) {
EnJj_SetupAction(enJj, EnJj_WaitToOpenMouth);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enJjUpdateHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enJjKillHook);
enJjUpdateHook = 0;
enJjKillHook = 0;
}
});
enJjKillHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) mutable {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enJjUpdateHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enJjKillHook);
enJjUpdateHook = 0;
enJjKillHook = 0;
});
}
if (actor->id == ACTOR_EN_OWL && gPlayState->sceneNum == SCENE_ZORAS_RIVER && if (actor->id == ACTOR_EN_OWL && gPlayState->sceneNum == SCENE_ZORAS_RIVER &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 0) == 2) { CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 0) == 2) {
Actor_Kill(actor); Actor_Kill(actor);
@ -1386,14 +1428,35 @@ void TimeSaverRegisterHooks() {
}); });
} }
void RegisterSkipWaterTempleGateDelay() { void RegisterSkipTimerDelay() {
// Skip Water Temple gate delay
COND_ID_HOOK(OnActorUpdate, ACTOR_BG_SPOT06_OBJECTS, COND_ID_HOOK(OnActorUpdate, ACTOR_BG_SPOT06_OBJECTS,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), [](void* actor) { CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), [](void* actor) {
BgSpot06Objects* spot06 = static_cast<BgSpot06Objects*>(actor); auto spot06 = static_cast<BgSpot06Objects*>(actor);
if (spot06->dyna.actor.params == 0) { if (spot06->dyna.actor.params == 0) {
spot06->timer = 0; spot06->timer = 0;
} }
}) });
// Skip Spirit Sun on Floor activation delay
COND_ID_HOOK(OnActorUpdate, ACTOR_BG_JYA_BOMBCHUIWA,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), [](void* actor) {
auto jya = static_cast<BgJyaBombchuiwa*>(actor);
if (!(jya->drawFlags & 4) && jya->timer > 0 && jya->timer < 9) {
jya->timer = 9;
}
});
// Skip Spirit Sun on Floor & Sun on Block activation delay
COND_ID_HOOK(OnActorUpdate, ACTOR_OBJ_LIGHTSWITCH,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), [](void* actor) {
if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE &&
(gPlayState->roomCtx.curRoom.num == 4 || gPlayState->roomCtx.curRoom.num == 8)) {
auto sun = static_cast<ObjLightswitch*>(actor);
sun->toggleDelay = 0;
}
});
} }
static RegisterShipInitFunc skipWaterTempleGateDelay(RegisterSkipWaterTempleGateDelay); static RegisterShipInitFunc skipTimerDelay(RegisterSkipTimerDelay,
{ CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" });

View file

@ -1,12 +1,11 @@
#include <vector>
#include <fstream>
#include <filesystem>
#include "TimeSplits.h" #include "TimeSplits.h"
#include "soh/Enhancements/gameplaystats.h" #include "soh/Enhancements/gameplaystats.h"
#include "soh/SaveManager.h" #include "soh/SaveManager.h"
#include "soh/util.h" #include "soh/util.h"
#include <vector>
#include "include/z64item.h"
#include <fstream>
#include <filesystem>
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor.h"
@ -17,6 +16,7 @@
#include "soh/SohGui/UIWidgets.hpp" #include "soh/SohGui/UIWidgets.hpp"
extern "C" { extern "C" {
#include "z64item.h"
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
extern PlayState* gPlayState; extern PlayState* gPlayState;
} }

View file

@ -3,17 +3,6 @@
#define TIMESPLITS_H #define TIMESPLITS_H
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif // TIMESPLITS_H
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -66,3 +55,5 @@ typedef struct {
} SplitObject; } SplitObject;
#endif #endif
#endif // TIMESPLITS_H

View file

@ -370,9 +370,16 @@ void RegisterOnKaleidoscopeUpdateHook() {
auto translation = GetParameritizedText("magic", TEXT_BANK_KALEIDO, arg); auto translation = GetParameritizedText("magic", TEXT_BANK_KALEIDO, arg);
SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode());
} else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { } else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) {
if (gPlayState->sceneNum >= SCENE_FOREST_TEMPLE && gPlayState->sceneNum <= SCENE_INSIDE_GANONS_CASTLE) {
snprintf(arg, sizeof(arg), "%d",
std::max(gSaveContext.inventory.dungeonKeys[gPlayState->sceneNum], (s8)0));
auto translation = GetParameritizedText("keys", TEXT_BANK_KALEIDO, arg);
SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode());
} else {
snprintf(arg, sizeof(arg), "%d", gSaveContext.rupees); snprintf(arg, sizeof(arg), "%d", gSaveContext.rupees);
auto translation = GetParameritizedText("rupees", TEXT_BANK_KALEIDO, arg); auto translation = GetParameritizedText("rupees", TEXT_BANK_KALEIDO, arg);
SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode());
}
} else if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) { } else if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) {
// TODO: announce timer? // TODO: announce timer?
} }

View file

@ -136,9 +136,11 @@ void CrowdControl::EmitMessage(uint32_t eventId, long timeRemaining, EffectResul
CrowdControl::EffectResult CrowdControl::ExecuteEffect(Effect* effect) { CrowdControl::EffectResult CrowdControl::ExecuteEffect(Effect* effect) {
GameInteractionEffectQueryResult giResult; GameInteractionEffectQueryResult giResult;
if (effect->category == kEffectCatSpawnEnemy) { if (effect->category == kEffectCatSpawnEnemy) {
giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->spawnParams[0], effect->spawnParams[1]); giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->spawnParams[0], effect->spawnParams[1],
effect->viewerName);
} else if (effect->category == kEffectCatSpawnActor) { } else if (effect->category == kEffectCatSpawnActor) {
giResult = GameInteractor::RawAction::SpawnActor(effect->spawnParams[0], effect->spawnParams[1]); giResult =
GameInteractor::RawAction::SpawnActor(effect->spawnParams[0], effect->spawnParams[1], effect->viewerName);
} else { } else {
giResult = GameInteractor::ApplyEffect(effect->giEffect); giResult = GameInteractor::ApplyEffect(effect->giEffect);
} }
@ -185,6 +187,7 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) {
Effect* effect = new Effect(); Effect* effect = new Effect();
effect->lastExecutionResult = EffectResult::Initiate; effect->lastExecutionResult = EffectResult::Initiate;
effect->id = dataReceived["id"]; effect->id = dataReceived["id"];
effect->viewerName = dataReceived["viewer"];
auto parameters = dataReceived["parameters"]; auto parameters = dataReceived["parameters"];
uint32_t receivedParameter = 0; uint32_t receivedParameter = 0;
auto effectName = dataReceived["code"].get<std::string>(); auto effectName = dataReceived["code"].get<std::string>();
@ -301,13 +304,13 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) {
case kEffectIncreaseSpeed: case kEffectIncreaseSpeed:
effect->category = kEffectCatSpeed; effect->category = kEffectCatSpeed;
effect->timeRemaining = 30000; effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier(); effect->giEffect = new GameInteractionEffect::ModifyMovementSpeedMultiplier();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = 2; dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = 2;
break; break;
case kEffectDecreaseSpeed: case kEffectDecreaseSpeed:
effect->category = kEffectCatSpeed; effect->category = kEffectCatSpeed;
effect->timeRemaining = 30000; effect->timeRemaining = 30000;
effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier(); effect->giEffect = new GameInteractionEffect::ModifyMovementSpeedMultiplier();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = -2; dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = -2;
break; break;
case kEffectLowGravity: case kEffectLowGravity:
@ -620,147 +623,6 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) {
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TP_DEST_PRELUDE; dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_TP_DEST_PRELUDE;
break; break;
// Tunic Color (Bidding War)
case kEffectTunicRed:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_RED;
break;
case kEffectTunicGreen:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_GREEN;
break;
case kEffectTunicBlue:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLUE;
break;
case kEffectTunicOrange:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE;
break;
case kEffectTunicYellow:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW;
break;
case kEffectTunicPurple:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE;
break;
case kEffectTunicPink:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PINK;
break;
case kEffectTunicBrown:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BROWN;
break;
case kEffectTunicBlack:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLACK;
break;
// Navi Color (Bidding War)
case kEffectNaviRed:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_RED;
break;
case kEffectNaviGreen:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_GREEN;
break;
case kEffectNaviBlue:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLUE;
break;
case kEffectNaviOrange:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE;
break;
case kEffectNaviYellow:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW;
break;
case kEffectNaviPurple:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE;
break;
case kEffectNaviPink:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PINK;
break;
case kEffectNaviBrown:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BROWN;
break;
case kEffectNaviBlack:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLACK;
break;
// Link's Hair Color (Bidding War)
case kEffectHairRed:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_RED;
break;
case kEffectHairGreen:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_GREEN;
break;
case kEffectHairBlue:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLUE;
break;
case kEffectHairOrange:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE;
break;
case kEffectHairYellow:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW;
break;
case kEffectHairPurple:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE;
break;
case kEffectHairPink:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_PINK;
break;
case kEffectHairBrown:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BROWN;
break;
case kEffectHairBlack:
effect->giEffect = new GameInteractionEffect::SetCosmeticsColor();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR;
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect)->parameters[1] = GI_COLOR_BLACK;
break;
default: default:
break; break;
} }

View file

@ -56,6 +56,7 @@ class CrowdControl : public Network {
uint32_t category = 0; uint32_t category = 0;
long timeRemaining; long timeRemaining;
GameInteractionEffectBase* giEffect; GameInteractionEffectBase* giEffect;
std::string viewerName;
// Metadata used while executing (only for timed effects) // Metadata used while executing (only for timed effects)
bool isPaused; bool isPaused;

View file

@ -124,50 +124,5 @@ public class ShipOfHarkinian : SimpleTCPPack<SimpleTCPServerConnector>
new("Requiem Destination", "tp_requiem") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to Desert Colossus." }, new("Requiem Destination", "tp_requiem") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to Desert Colossus." },
new("Nocturne Destination", "tp_nocturne") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Raveyard." }, new("Nocturne Destination", "tp_nocturne") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Raveyard." },
new("Prelude Destination", "tp_prelude") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Temple of Time." }, new("Prelude Destination", "tp_prelude") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Temple of Time." },
// Tunic Color (Bidding War)
new("Tunic Color", "tunic", ItemKind.BidWar)
{
Parameters = new ParameterDef("Color", "color_tunic_param",
new Parameter("Red", "red"),
new Parameter("Green", "green"),
new Parameter("Blue", "blue"),
new Parameter("Orange", "orange"),
new Parameter("Yellow", "yellow"),
new Parameter("Purple", "purple"),
new Parameter("Pink", "pink"),
new Parameter("Brown", "brown"),
new Parameter("Black", "black"))
},
// Navi Color (Bidding War)
new("Navi Color", "navi", ItemKind.BidWar)
{
Parameters = new ParameterDef("Color", "color_navi_param",
new Parameter("Red", "red"),
new Parameter("Green", "green"),
new Parameter("Blue", "blue"),
new Parameter("Orange", "orange"),
new Parameter("Yellow", "yellow"),
new Parameter("Purple", "purple"),
new Parameter("Pink", "pink"),
new Parameter("Brown", "brown"),
new Parameter("Black", "black"))
},
// Link's Hair Color (Bidding War)
new("Link's Hair Color", "hair", ItemKind.BidWar)
{
Parameters = new ParameterDef("Color", "color_hair_param",
new Parameter("Red", "red"),
new Parameter("Green", "green"),
new Parameter("Blue", "blue"),
new Parameter("Orange", "orange"),
new Parameter("Yellow", "yellow"),
new Parameter("Purple", "purple"),
new Parameter("Pink", "pink"),
new Parameter("Brown", "brown"),
new Parameter("Black", "black"))
}
}; };
} }

View file

@ -242,8 +242,8 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) {
effect->parameters[0] = payload["parameters"][0].get<int32_t>(); effect->parameters[0] = payload["parameters"][0].get<int32_t>();
} }
return effect; return effect;
} else if (name == "ModifyRunSpeedModifier") { } else if (name == "ModifyMovementSpeedMultiplier") {
auto effect = new GameInteractionEffect::ModifyRunSpeedModifier(); auto effect = new GameInteractionEffect::ModifyMovementSpeedMultiplier();
if (payload.contains("parameters")) { if (payload.contains("parameters")) {
effect->parameters[0] = payload["parameters"][0].get<int32_t>(); effect->parameters[0] = payload["parameters"][0].get<int32_t>();
} }
@ -282,13 +282,6 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) {
return effect; return effect;
} else if (name == "SetCollisionViewer") { } else if (name == "SetCollisionViewer") {
return new GameInteractionEffect::SetCollisionViewer(); return new GameInteractionEffect::SetCollisionViewer();
} else if (name == "SetCosmeticsColor") {
auto effect = new GameInteractionEffect::SetCosmeticsColor();
if (payload.contains("parameters")) {
effect->parameters[0] = payload["parameters"][0].get<int32_t>();
effect->parameters[1] = payload["parameters"][1].get<int32_t>();
}
return effect;
} else if (name == "RandomizeCosmetics") { } else if (name == "RandomizeCosmetics") {
return new GameInteractionEffect::RandomizeCosmetics(); return new GameInteractionEffect::RandomizeCosmetics();
} else if (name == "PressButton") { } else if (name == "PressButton") {

View file

@ -2329,7 +2329,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
} }
} else if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { } else if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) {
// rando hints at altar // rando hints at altar
messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage(MF_AUTO_FORMAT)
: ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT);
} else if (textId == TEXT_GANONDORF) { } else if (textId == TEXT_GANONDORF) {
if (ctx->GetOption(RSK_GANONDORF_HINT)) { if (ctx->GetOption(RSK_GANONDORF_HINT)) {

View file

@ -180,6 +180,9 @@ void SaveManager::LoadRandomizer() {
// all ItemLocations is 0 anyway. // all ItemLocations is 0 anyway.
randoContext->GetItemLocation(i)->SetCustomPrice(price); randoContext->GetItemLocation(i)->SetCustomPrice(price);
} }
bool excluded = false;
SaveManager::Instance->LoadData("excluded", excluded, false);
randoContext->GetItemLocation(i)->SetExcludedOption(excluded);
}); });
}); });
@ -271,6 +274,9 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f
randoContext->GetItemOverride(i).GetTrickName().GetFrench()); randoContext->GetItemOverride(i).GetTrickName().GetFrench());
}); });
} }
if (randoContext->GetItemLocation(i)->IsExcluded()) {
SaveManager::Instance->SaveData("excluded", true);
}
if (randoContext->GetItemLocation(i)->HasCustomPrice()) { if (randoContext->GetItemLocation(i)->HasCustomPrice()) {
SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice()); SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice());
} }

View file

@ -27,7 +27,6 @@ void disableBetaQuest();
#endif #endif
namespace SohGui { namespace SohGui {
static std::unordered_map<int32_t, const char*> languages = { static std::unordered_map<int32_t, const char*> languages = {
{ LANGUAGE_ENG, "English" }, { LANGUAGE_ENG, "English" },
{ LANGUAGE_GER, "German" }, { LANGUAGE_GER, "German" },
@ -35,164 +34,6 @@ static std::unordered_map<int32_t, const char*> languages = {
{ LANGUAGE_JPN, "Japanese" }, { LANGUAGE_JPN, "Japanese" },
}; };
static const std::unordered_map<int32_t, const char*> menuThemeOptions = {
{ UIWidgets::Colors::Red, "Red" },
{ UIWidgets::Colors::DarkRed, "Dark Red" },
{ UIWidgets::Colors::Orange, "Orange" },
{ UIWidgets::Colors::Green, "Green" },
{ UIWidgets::Colors::DarkGreen, "Dark Green" },
{ UIWidgets::Colors::LightBlue, "Light Blue" },
{ UIWidgets::Colors::Blue, "Blue" },
{ UIWidgets::Colors::DarkBlue, "Dark Blue" },
{ UIWidgets::Colors::Indigo, "Indigo" },
{ UIWidgets::Colors::Violet, "Violet" },
{ UIWidgets::Colors::Purple, "Purple" },
{ UIWidgets::Colors::Brown, "Brown" },
{ UIWidgets::Colors::Gray, "Gray" },
{ UIWidgets::Colors::DarkGray, "Dark Gray" },
};
static const std::unordered_map<int32_t, const char*> textureFilteringMap = {
{ Fast::FILTER_THREE_POINT, "Three-Point" },
{ Fast::FILTER_LINEAR, "Linear" },
{ Fast::FILTER_NONE, "None" },
};
static const std::unordered_map<int32_t, const char*> logLevels = {
{ DEBUG_LOG_TRACE, "Trace" }, { DEBUG_LOG_DEBUG, "Debug" }, { DEBUG_LOG_INFO, "Info" },
{ DEBUG_LOG_WARN, "Warn" }, { DEBUG_LOG_ERROR, "Error" }, { DEBUG_LOG_CRITICAL, "Critical" },
{ DEBUG_LOG_OFF, "Off" },
};
static const std::unordered_map<int32_t, const char*> notificationPosition = {
{ 0, "Top Left" }, { 1, "Top Right" }, { 2, "Bottom Left" }, { 3, "Bottom Right" }, { 4, "Hidden" },
};
static const std::unordered_map<int32_t, const char*> dekuStickCheat = {
{ DEKU_STICK_NORMAL, "Normal" },
{ DEKU_STICK_UNBREAKABLE, "Unbreakable" },
{ DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, "Unbreakable + Always on Fire" },
};
static const std::unordered_map<int32_t, const char*> skipForcedDialogOptions = {
{ FORCED_DIALOG_SKIP_NONE, "None" },
{ FORCED_DIALOG_SKIP_NAVI, "Navi" },
{ FORCED_DIALOG_SKIP_NPC, "NPCs" },
{ FORCED_DIALOG_SKIP_ALL, "All" },
};
static const std::unordered_map<int32_t, const char*> skipGetItemAnimationOptions = {
{ SGIA_DISABLED, "Disabled" },
{ SGIA_JUNK, "Junk Items" },
{ SGIA_ALL, "All Items" },
};
static const std::unordered_map<int32_t, const char*> chestStyleMatchesContentsOptions = {
{ CSMC_DISABLED, "Disabled" },
{ CSMC_BOTH, "Both" },
{ CSMC_TEXTURE, "Texture Only" },
{ CSMC_SIZE, "Size Only" },
};
static const std::unordered_map<int32_t, const char*> timeTravelOptions = {
{ TIME_TRAVEL_DISABLED, "Disabled" },
{ TIME_TRAVEL_OOT, "Ocarina of Time" },
{ TIME_TRAVEL_ANY, "Any Ocarina" },
};
static const std::unordered_map<int32_t, const char*> sleepingWaterfallOptions = {
{ WATERFALL_ALWAYS, "Always" },
{ WATERFALL_ONCE, "Once" },
{ WATERFALL_NEVER, "Never" },
};
static const std::unordered_map<int32_t, const char*> allPowers = {
{ DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" },
{ DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" },
{ DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" },
{ DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" },
{ DAMAGE_OHKO, "OHKO (256x)" },
};
static const std::unordered_map<int32_t, const char*> subPowers = {
{ DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" },
{ DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" },
{ DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" },
{ DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" },
};
static const std::unordered_map<int32_t, const char*> subSubPowers = {
{ DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" },
{ DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" },
{ DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" },
{ DAMAGE_MERCILESS, "Merciless (64x)" },
};
static const std::unordered_map<int32_t, const char*> bonkDamageValues = {
{ BONK_DAMAGE_NONE, "No Damage" }, { BONK_DAMAGE_QUARTER_HEART, "0.25 Hearts" },
{ BONK_DAMAGE_HALF_HEART, "0.5 Hearts" }, { BONK_DAMAGE_1_HEART, "1 Heart" },
{ BONK_DAMAGE_2_HEARTS, "2 Hearts" }, { BONK_DAMAGE_4_HEARTS, "4 Hearts" },
{ BONK_DAMAGE_8_HEARTS, "8 Hearts" }, { BONK_DAMAGE_OHKO, "OHKO" },
};
static const std::unordered_map<int32_t, const char*> dampeDropRates = {
{ DAMPE_NONE, "None" },
{ DAMPE_NORMAL, "Vanilla" },
{ DAMPE_JALAPENO, "Jalapeño" },
{ DAMPE_CHIPOTLE, "Serrano" },
{ DAMPE_SCOTCH_BONNET, "Habanero" },
{ DAMPE_GHOST_PEPPER, "Ghost Pepper" },
{ DAMPE_INFERNO, "Dampe's Inferno" },
};
static const std::unordered_map<int32_t, const char*> cursorAnywhereValues = {
{ PAUSE_ANY_CURSOR_RANDO_ONLY, "Only in Rando" },
{ PAUSE_ANY_CURSOR_ALWAYS_ON, "Always" },
{ PAUSE_ANY_CURSOR_ALWAYS_OFF, "Never" },
};
static const std::unordered_map<int32_t, const char*> swordToggleModes = {
{ SWORD_TOGGLE_NONE, "None" },
{ SWORD_TOGGLE_CHILD, "Child Toggle" },
{ SWORD_TOGGLE_BOTH_AGES, "Both Ages" },
};
static const std::unordered_map<int32_t, const char*> zFightingOptions = {
{ ZFIGHT_FIX_DISABLED, "Disabled" },
{ ZFIGHT_FIX_CONSISTENT_VANISH, "Consistent Vanish" },
{ ZFIGHT_FIX_NO_VANISH, "No Vanish" },
};
static const std::unordered_map<int32_t, const char*> mirroredWorldModes = {
{ MIRRORED_WORLD_OFF, "Disabled" },
{ MIRRORED_WORLD_ALWAYS, "Always" },
{ MIRRORED_WORLD_RANDOM, "Random" },
{ MIRRORED_WORLD_RANDOM_SEEDED, "Random (Seeded)" },
{ MIRRORED_WORLD_DUNGEONS_ALL, "Dungeons" },
{ MIRRORED_WORLD_DUNGEONS_VANILLA, "Dungeons (Vanilla)" },
{ MIRRORED_WORLD_DUNGEONS_MQ, "Dungeons (MQ)" },
{ MIRRORED_WORLD_DUNGEONS_RANDOM, "Dungeons Random" },
{ MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED, "Dungeons Random (Seeded)" },
};
static const std::unordered_map<int32_t, const char*> enemyRandomizerModes = {
{ ENEMY_RANDOMIZER_OFF, "Disabled" },
{ ENEMY_RANDOMIZER_RANDOM, "Random" },
{ ENEMY_RANDOMIZER_RANDOM_SEEDED, "Random (Seeded)" },
};
static const std::unordered_map<int32_t, const char*> debugSaveFileModes = {
{ 0, "Off" },
{ 1, "Vanilla" },
{ 2, "Maxed" },
};
static const std::unordered_map<int32_t, const char*> bootSequenceLabels = {
{ BOOTSEQUENCE_DEFAULT, "Default" },
{ BOOTSEQUENCE_AUTHENTIC, "Authentic" },
{ BOOTSEQUENCE_FILESELECT, "File Select" },
};
class SohMenu : public Ship::Menu { class SohMenu : public Ship::Menu {
public: public:
SohMenu(const std::string& consoleVariable, const std::string& name); SohMenu(const std::string& consoleVariable, const std::string& name);

View file

@ -5,6 +5,18 @@ namespace SohGui {
extern std::shared_ptr<SohMenu> mSohMenu; extern std::shared_ptr<SohMenu> mSohMenu;
using namespace UIWidgets; using namespace UIWidgets;
static const std::unordered_map<int32_t, const char*> logLevels = {
{ DEBUG_LOG_TRACE, "Trace" }, { DEBUG_LOG_DEBUG, "Debug" }, { DEBUG_LOG_INFO, "Info" },
{ DEBUG_LOG_WARN, "Warn" }, { DEBUG_LOG_ERROR, "Error" }, { DEBUG_LOG_CRITICAL, "Critical" },
{ DEBUG_LOG_OFF, "Off" },
};
static const std::unordered_map<int32_t, const char*> debugSaveFileModes = {
{ 0, "Off" },
{ 1, "Vanilla" },
{ 2, "Maxed" },
};
void SohMenu::AddMenuDevTools() { void SohMenu::AddMenuDevTools() {
// Add Dev Tools Menu // Add Dev Tools Menu
AddMenuEntry("Dev Tools", CVAR_SETTING("Menu.DevToolsSidebarSection")); AddMenuEntry("Dev Tools", CVAR_SETTING("Menu.DevToolsSidebarSection"));

View file

@ -1,4 +1,4 @@
#include "SohMenu.h" #include "SohMenu.h"
#include <soh/Enhancements/mods.h> #include <soh/Enhancements/mods.h>
#include <soh/Enhancements/game-interactor/GameInteractor.h> #include <soh/Enhancements/game-interactor/GameInteractor.h>
#include <soh/OTRGlobals.h> #include <soh/OTRGlobals.h>
@ -6,13 +6,12 @@
#include <soh/Enhancements/enemyrandomizer.h> #include <soh/Enhancements/enemyrandomizer.h>
#include <soh/Enhancements/TimeDisplay/TimeDisplay.h> #include <soh/Enhancements/TimeDisplay/TimeDisplay.h>
#define CVAR_INT_SHIP_INIT(cvar, val) \
CVarSetInteger(cvar, val); \
ShipInit::Init(cvar);
static std::string comboboxTooltip = ""; static std::string comboboxTooltip = "";
bool isBetaQuestEnabled = false; bool isBetaQuestEnabled = false;
static std::unordered_map<int32_t, const char*> bunnyHoodEffectMap = {
{ BUNNY_HOOD_VANILLA, "Vanilla" },
{ BUNNY_HOOD_FAST, "Faster Run" },
{ BUNNY_HOOD_FAST_AND_JUMP, "Faster + Longer Jump" },
};
extern "C" { extern "C" {
void enableBetaQuest() { void enableBetaQuest() {
@ -28,6 +27,119 @@ namespace SohGui {
extern std::shared_ptr<SohMenu> mSohMenu; extern std::shared_ptr<SohMenu> mSohMenu;
using namespace UIWidgets; using namespace UIWidgets;
static std::unordered_map<int32_t, const char*> bunnyHoodEffectMap = {
{ BUNNY_HOOD_VANILLA, "Vanilla" },
{ BUNNY_HOOD_FAST, "Faster Run" },
{ BUNNY_HOOD_FAST_AND_JUMP, "Faster + Longer Jump" },
};
static const std::unordered_map<int32_t, const char*> dekuStickCheat = {
{ DEKU_STICK_NORMAL, "Normal" },
{ DEKU_STICK_UNBREAKABLE, "Unbreakable" },
{ DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, "Unbreakable + Always on Fire" },
};
static const std::unordered_map<int32_t, const char*> skipForcedDialogOptions = {
{ FORCED_DIALOG_SKIP_NONE, "None" },
{ FORCED_DIALOG_SKIP_NAVI, "Navi" },
{ FORCED_DIALOG_SKIP_NPC, "NPCs" },
{ FORCED_DIALOG_SKIP_ALL, "All" },
};
static const std::unordered_map<int32_t, const char*> chestStyleMatchesContentsOptions = {
{ CSMC_DISABLED, "Disabled" },
{ CSMC_BOTH, "Both" },
{ CSMC_TEXTURE, "Texture Only" },
{ CSMC_SIZE, "Size Only" },
};
static const std::unordered_map<int32_t, const char*> timeTravelOptions = {
{ TIME_TRAVEL_DISABLED, "Disabled" },
{ TIME_TRAVEL_OOT, "Ocarina of Time" },
{ TIME_TRAVEL_ANY, "Any Ocarina" },
};
static const std::unordered_map<int32_t, const char*> sleepingWaterfallOptions = {
{ WATERFALL_ALWAYS, "Always" },
{ WATERFALL_ONCE, "Once" },
{ WATERFALL_NEVER, "Never" },
};
static const std::unordered_map<int32_t, const char*> allPowers = {
{ DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" },
{ DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" },
{ DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" },
{ DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" },
{ DAMAGE_OHKO, "OHKO (256x)" },
};
static const std::unordered_map<int32_t, const char*> subPowers = {
{ DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" },
{ DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" },
{ DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" },
{ DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" },
};
static const std::unordered_map<int32_t, const char*> subSubPowers = {
{ DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" },
{ DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" },
{ DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" },
{ DAMAGE_MERCILESS, "Merciless (64x)" },
};
static const std::unordered_map<int32_t, const char*> bonkDamageValues = {
{ BONK_DAMAGE_NONE, "No Damage" }, { BONK_DAMAGE_QUARTER_HEART, "0.25 Hearts" },
{ BONK_DAMAGE_HALF_HEART, "0.5 Hearts" }, { BONK_DAMAGE_1_HEART, "1 Heart" },
{ BONK_DAMAGE_2_HEARTS, "2 Hearts" }, { BONK_DAMAGE_4_HEARTS, "4 Hearts" },
{ BONK_DAMAGE_8_HEARTS, "8 Hearts" }, { BONK_DAMAGE_OHKO, "OHKO" },
};
static const std::unordered_map<int32_t, const char*> dampeDropRates = {
{ DAMPE_NONE, "None" },
{ DAMPE_NORMAL, "Vanilla" },
{ DAMPE_JALAPENO, "Jalapeño" },
{ DAMPE_CHIPOTLE, "Serrano" },
{ DAMPE_SCOTCH_BONNET, "Habanero" },
{ DAMPE_GHOST_PEPPER, "Ghost Pepper" },
{ DAMPE_INFERNO, "Dampe's Inferno" },
};
static const std::unordered_map<int32_t, const char*> cursorAnywhereValues = {
{ PAUSE_ANY_CURSOR_RANDO_ONLY, "Only in Rando" },
{ PAUSE_ANY_CURSOR_ALWAYS_ON, "Always" },
{ PAUSE_ANY_CURSOR_ALWAYS_OFF, "Never" },
};
static const std::unordered_map<int32_t, const char*> zFightingOptions = {
{ ZFIGHT_FIX_DISABLED, "Disabled" },
{ ZFIGHT_FIX_CONSISTENT_VANISH, "Consistent Vanish" },
{ ZFIGHT_FIX_NO_VANISH, "No Vanish" },
};
static const std::unordered_map<int32_t, const char*> swordToggleModes = {
{ SWORD_TOGGLE_NONE, "None" },
{ SWORD_TOGGLE_CHILD, "Child Toggle" },
{ SWORD_TOGGLE_BOTH_AGES, "Both Ages" },
};
static const std::unordered_map<int32_t, const char*> mirroredWorldModes = {
{ MIRRORED_WORLD_OFF, "Disabled" },
{ MIRRORED_WORLD_ALWAYS, "Always" },
{ MIRRORED_WORLD_RANDOM, "Random" },
{ MIRRORED_WORLD_RANDOM_SEEDED, "Random (Seeded)" },
{ MIRRORED_WORLD_DUNGEONS_ALL, "Dungeons" },
{ MIRRORED_WORLD_DUNGEONS_VANILLA, "Dungeons (Vanilla)" },
{ MIRRORED_WORLD_DUNGEONS_MQ, "Dungeons (MQ)" },
{ MIRRORED_WORLD_DUNGEONS_RANDOM, "Dungeons Random" },
{ MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED, "Dungeons Random (Seeded)" },
};
static const std::unordered_map<int32_t, const char*> enemyRandomizerModes = {
{ ENEMY_RANDOMIZER_OFF, "Disabled" },
{ ENEMY_RANDOMIZER_RANDOM, "Random" },
{ ENEMY_RANDOMIZER_RANDOM_SEEDED, "Random (Seeded)" },
};
void SohMenu::AddMenuEnhancements() { void SohMenu::AddMenuEnhancements() {
// Add Enhancements Menu // Add Enhancements Menu
AddMenuEntry("Enhancements", CVAR_SETTING("Menu.EnhancementsSidebarSection")); AddMenuEntry("Enhancements", CVAR_SETTING("Menu.EnhancementsSidebarSection"));
@ -217,6 +329,15 @@ void SohMenu::AddMenuEnhancements() {
"open permanently.\n" "open permanently.\n"
"Never: Link never needs to play Zelda's Lullaby to open the waterfall. He only needs to have " "Never: Link never needs to play Zelda's Lullaby to open the waterfall. He only needs to have "
"learned it and have an Ocarina.")); "learned it and have an Ocarina."));
AddWidget(path, "Skip Feeding Jabu-Jabu", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("TimeSavers.SkipJabuJabuFish"))
.PreFunc([](WidgetInfo& info) {
info.options->disabled =
IS_RANDO && OTRGlobals::Instance->gRandoContext->GetOption(RSK_JABU_OPEN).Is(RO_JABU_OPEN);
info.options->disabledTooltip =
"This setting is disabled because a randomizer savefile with \"Jabu-Jaby: Open\" is loaded.";
})
.Options(CheckboxOptions().Tooltip("Allow Link to enter Jabu-Jabu without feeding him a fish."));
// Skips & Speed-ups // Skips & Speed-ups
path.sidebarName = "Skips & Speed-ups"; path.sidebarName = "Skips & Speed-ups";
@ -227,16 +348,16 @@ void SohMenu::AddMenuEnhancements() {
AddWidget(path, "All##Skips", WIDGET_BUTTON) AddWidget(path, "All##Skips", WIDGET_BUTTON)
.Options(ButtonOptions().Size(Sizes::Inline)) .Options(ButtonOptions().Size(Sizes::Inline))
.Callback([](WidgetInfo& info) { .Callback([](WidgetInfo& info) {
CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), true); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), true);
CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), true); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), true);
CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), true); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), true);
CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), true); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), true);
CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), true); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), true);
CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), true); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), true);
CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), true); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), true);
CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), true); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), true);
CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), true); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), true);
CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), true); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), true);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}); });
@ -244,16 +365,16 @@ void SohMenu::AddMenuEnhancements() {
.SameLine(true) .SameLine(true)
.Options(ButtonOptions().Size(Sizes::Inline)) .Options(ButtonOptions().Size(Sizes::Inline))
.Callback([](WidgetInfo& info) { .Callback([](WidgetInfo& info) {
CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro")); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), false);
CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances")); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), false);
CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story")); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), false);
CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong")); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), false);
CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro")); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), false);
CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths")); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), false);
CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint")); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), false);
CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions")); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), false);
CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions")); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), false);
CVarClear(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard")); CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), false);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}); });
@ -467,7 +588,7 @@ void SohMenu::AddMenuEnhancements() {
.Options(CheckboxOptions().Tooltip( .Options(CheckboxOptions().Tooltip(
"Scales all of the Adult Equipment, as well as moving some a bit, to fit on Child Link better. May " "Scales all of the Adult Equipment, as well as moving some a bit, to fit on Child Link better. May "
"not work properly with some mods.")); "not work properly with some mods."));
AddWidget(path, "Show Gauntlets in First Person", WIDGET_CVAR_CHECKBOX) AddWidget(path, "Show Gauntlets in First-Person", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("FirstPersonGauntlets")) .CVar(CVAR_ENHANCEMENT("FirstPersonGauntlets"))
.RaceDisable(false) .RaceDisable(false)
.Options(CheckboxOptions().Tooltip("Renders Gauntlets when using the Bow and Hookshot like in OoT3D.")); .Options(CheckboxOptions().Tooltip("Renders Gauntlets when using the Bow and Hookshot like in OoT3D."));

View file

@ -96,21 +96,15 @@ void SohMenu::AddMenuNetwork() {
AddSidebarEntry("Network", path.sidebarName, 3); AddSidebarEntry("Network", path.sidebarName, 3);
path.column = SECTION_COLUMN_1; path.column = SECTION_COLUMN_1;
AddWidget(path, "About Crowd Control", WIDGET_SEPARATOR_TEXT);
AddWidget(path, AddWidget(path,
"Crowd Control is a platform that allows viewers to interact " "Crowd Control is a platform that allows viewers to interact "
"with a streamer's game in real time.\n" "with a streamer's game in real time.\n"
"\n" "\n"
"Click the question mark to copy the link to the Crowd Control " "Please head over to www.crowdcontrol.live for more information!",
"website to your clipboard.",
WIDGET_TEXT); WIDGET_TEXT);
AddWidget(path, ICON_FA_CLIPBOARD "##CrowdControl", WIDGET_BUTTON)
.Callback([](WidgetInfo& info) { AddWidget(path, "Connect to Crowd Control", WIDGET_SEPARATOR_TEXT);
ImGui::SetClipboardText("https://crowdcontrol.live");
Notification::Emit({
.message = "Copied to clipboard",
});
})
.Options(ButtonOptions().Tooltip("https://crowdcontrol.live"));
AddWidget(path, "Host & Port", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { AddWidget(path, "Host & Port", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) {
ImGui::BeginDisabled(CrowdControl::Instance->isEnabled || CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); ImGui::BeginDisabled(CrowdControl::Instance->isEnabled || CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
ImGui::Text("%s", info.name.c_str()); ImGui::Text("%s", info.name.c_str());
@ -155,14 +149,25 @@ void SohMenu::AddMenuNetwork() {
CrowdControl::Instance->Enable(); CrowdControl::Instance->Enable();
} }
}); });
AddWidget(path, "Connecting...##CrowdControl", WIDGET_TEXT).PreFunc([](WidgetInfo& info) { AddWidget(path, "Connecting...", WIDGET_TEXT).PreFunc([](WidgetInfo& info) {
info.isHidden = !CrowdControl::Instance->isEnabled; info.isHidden = !CrowdControl::Instance->isEnabled;
if (CrowdControl::Instance->isConnected) { if (CrowdControl::Instance->isConnected) {
info.name = "Connected##CrowdControl"; info.name = "Connected";
} else { } else {
info.name = "Connecting...##CrowdControl"; info.name = "Connecting...";
} }
}); });
AddWidget(path, "Additional Settings", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Enemy Name Tags", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"))
.RaceDisable(true)
.Options(CheckboxOptions().Tooltip(
"When viewers spawn enemies, the enemy will have a name tag above them with the viewer's name."));
AddWidget(path, "Spawned Enemies Ignored Ingame", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"))
.RaceDisable(true)
.Options(CheckboxOptions().Tooltip("Enemies spawned by CrowdControl won't be considered for \"clear enemy "
"rooms\", so they don't need to be killed to complete these rooms."));
} }
} // namespace SohGui } // namespace SohGui

View file

@ -6,6 +6,12 @@ namespace SohGui {
extern std::shared_ptr<SohMenu> mSohMenu; extern std::shared_ptr<SohMenu> mSohMenu;
using namespace UIWidgets; using namespace UIWidgets;
static const std::unordered_map<int32_t, const char*> skipGetItemAnimationOptions = {
{ SGIA_DISABLED, "Disabled" },
{ SGIA_JUNK, "Junk Items" },
{ SGIA_ALL, "All Items" },
};
void SohMenu::AddMenuRandomizer() { void SohMenu::AddMenuRandomizer() {
// Add Randomizer Menu // Add Randomizer Menu
AddMenuEntry("Randomizer", CVAR_SETTING("Menu.RandomizerSidebarSection")); AddMenuEntry("Randomizer", CVAR_SETTING("Menu.RandomizerSidebarSection"));

View file

@ -23,6 +23,39 @@ static std::unordered_map<int32_t, const char*> imguiScaleOptions = {
{ 3, "X-Large" }, { 3, "X-Large" },
}; };
static const std::unordered_map<int32_t, const char*> menuThemeOptions = {
{ UIWidgets::Colors::Red, "Red" },
{ UIWidgets::Colors::DarkRed, "Dark Red" },
{ UIWidgets::Colors::Orange, "Orange" },
{ UIWidgets::Colors::Green, "Green" },
{ UIWidgets::Colors::DarkGreen, "Dark Green" },
{ UIWidgets::Colors::LightBlue, "Light Blue" },
{ UIWidgets::Colors::Blue, "Blue" },
{ UIWidgets::Colors::DarkBlue, "Dark Blue" },
{ UIWidgets::Colors::Indigo, "Indigo" },
{ UIWidgets::Colors::Violet, "Violet" },
{ UIWidgets::Colors::Purple, "Purple" },
{ UIWidgets::Colors::Brown, "Brown" },
{ UIWidgets::Colors::Gray, "Gray" },
{ UIWidgets::Colors::DarkGray, "Dark Gray" },
};
static const std::unordered_map<int32_t, const char*> textureFilteringMap = {
{ Fast::FILTER_THREE_POINT, "Three-Point" },
{ Fast::FILTER_LINEAR, "Linear" },
{ Fast::FILTER_NONE, "None" },
};
static const std::unordered_map<int32_t, const char*> notificationPosition = {
{ 0, "Top Left" }, { 1, "Top Right" }, { 2, "Bottom Left" }, { 3, "Bottom Right" }, { 4, "Hidden" },
};
static const std::unordered_map<int32_t, const char*> bootSequenceLabels = {
{ BOOTSEQUENCE_DEFAULT, "Default" },
{ BOOTSEQUENCE_AUTHENTIC, "Authentic" },
{ BOOTSEQUENCE_FILESELECT, "File Select" },
};
const char* GetGameVersionString(uint32_t index) { const char* GetGameVersionString(uint32_t index) {
uint32_t gameVersion = ResourceMgr_GetGameVersion(index); uint32_t gameVersion = ResourceMgr_GetGameVersion(index);
switch (gameVersion) { switch (gameVersion) {

View file

@ -115,10 +115,12 @@ struct WidgetOptions {
tooltip = tooltip_; tooltip = tooltip_;
return *this; return *this;
} }
WidgetOptions& Disabled(bool disabled_) { WidgetOptions& Disabled(bool disabled_) {
disabled = disabled_; disabled = disabled_;
return *this; return *this;
} }
WidgetOptions& DisabledTooltip(const char* disabledTooltip_) { WidgetOptions& DisabledTooltip(const char* disabledTooltip_) {
disabledTooltip = disabledTooltip_; disabledTooltip = disabledTooltip_;
return *this; return *this;
@ -143,14 +145,17 @@ struct ButtonOptions : WidgetOptions {
size = size_; size = size_;
return *this; return *this;
} }
ButtonOptions& Padding(ImVec2 padding_) { ButtonOptions& Padding(ImVec2 padding_) {
padding = padding_; padding = padding_;
return *this; return *this;
} }
ButtonOptions& Tooltip(const char* tooltip_) { ButtonOptions& Tooltip(const char* tooltip_) {
WidgetOptions::tooltip = tooltip_; WidgetOptions::tooltip = tooltip_;
return *this; return *this;
} }
ButtonOptions& Color(Colors color_) { ButtonOptions& Color(Colors color_) {
color = color_; color = color_;
return *this; return *this;
@ -168,22 +173,27 @@ struct WindowButtonOptions : WidgetOptions {
size = size_; size = size_;
return *this; return *this;
} }
WindowButtonOptions& Padding(ImVec2 padding_) { WindowButtonOptions& Padding(ImVec2 padding_) {
padding = padding_; padding = padding_;
return *this; return *this;
} }
WindowButtonOptions& Tooltip(const char* tooltip_) { WindowButtonOptions& Tooltip(const char* tooltip_) {
WidgetOptions::tooltip = tooltip_; WidgetOptions::tooltip = tooltip_;
return *this; return *this;
} }
WindowButtonOptions& Color(Colors color_) { WindowButtonOptions& Color(Colors color_) {
color = color_; color = color_;
return *this; return *this;
} }
WindowButtonOptions& ShowButton(bool showButton_) { WindowButtonOptions& ShowButton(bool showButton_) {
showButton = showButton_; showButton = showButton_;
return *this; return *this;
} }
WindowButtonOptions& EmbedWindow(bool embedWindow_) { WindowButtonOptions& EmbedWindow(bool embedWindow_) {
embedWindow = embedWindow_; embedWindow = embedWindow_;
return *this; return *this;
@ -201,26 +211,32 @@ struct CheckboxOptions : WidgetOptions {
defaultValue = defaultValue_; defaultValue = defaultValue_;
return *this; return *this;
} }
CheckboxOptions& ComponentAlignment(ComponentAlignments alignment_) { CheckboxOptions& ComponentAlignment(ComponentAlignments alignment_) {
alignment = alignment_; alignment = alignment_;
return *this; return *this;
} }
CheckboxOptions& LabelPosition(LabelPositions labelPosition_) { CheckboxOptions& LabelPosition(LabelPositions labelPosition_) {
labelPosition = labelPosition_; labelPosition = labelPosition_;
return *this; return *this;
} }
CheckboxOptions& Tooltip(const char* tooltip_) { CheckboxOptions& Tooltip(const char* tooltip_) {
WidgetOptions::tooltip = tooltip_; WidgetOptions::tooltip = tooltip_;
return *this; return *this;
} }
CheckboxOptions& Color(Colors color_) { CheckboxOptions& Color(Colors color_) {
color = color_; color = color_;
return *this; return *this;
} }
CheckboxOptions& DisabledTooltip(const char* disabledTooltip_) { CheckboxOptions& DisabledTooltip(const char* disabledTooltip_) {
WidgetOptions::disabledTooltip = disabledTooltip_; WidgetOptions::disabledTooltip = disabledTooltip_;
return *this; return *this;
} }
CheckboxOptions& Padding(ImVec2 padding_) { CheckboxOptions& Padding(ImVec2 padding_) {
padding = padding_; padding = padding_;
return *this; return *this;
@ -239,22 +255,27 @@ struct ComboboxOptions : WidgetOptions {
comboMap = comboMap_; comboMap = comboMap_;
return *this; return *this;
} }
ComboboxOptions& DefaultIndex(uint32_t defaultIndex_) { ComboboxOptions& DefaultIndex(uint32_t defaultIndex_) {
defaultIndex = defaultIndex_; defaultIndex = defaultIndex_;
return *this; return *this;
} }
ComboboxOptions& ComponentAlignment(ComponentAlignments alignment_) { ComboboxOptions& ComponentAlignment(ComponentAlignments alignment_) {
alignment = alignment_; alignment = alignment_;
return *this; return *this;
} }
ComboboxOptions& LabelPosition(LabelPositions labelPosition_) { ComboboxOptions& LabelPosition(LabelPositions labelPosition_) {
labelPosition = labelPosition_; labelPosition = labelPosition_;
return *this; return *this;
} }
ComboboxOptions& Tooltip(const char* tooltip_) { ComboboxOptions& Tooltip(const char* tooltip_) {
WidgetOptions::tooltip = tooltip_; WidgetOptions::tooltip = tooltip_;
return *this; return *this;
} }
ComboboxOptions& Color(Colors color_) { ComboboxOptions& Color(Colors color_) {
color = color_; color = color_;
return *this; return *this;
@ -279,46 +300,57 @@ struct IntSliderOptions : WidgetOptions {
showButtons = showButtons_; showButtons = showButtons_;
return *this; return *this;
} }
IntSliderOptions& Format(const char* format_) { IntSliderOptions& Format(const char* format_) {
format = format_; format = format_;
return *this; return *this;
} }
IntSliderOptions& Step(int32_t step_) { IntSliderOptions& Step(int32_t step_) {
step = step_; step = step_;
return *this; return *this;
} }
IntSliderOptions& Min(int32_t min_) { IntSliderOptions& Min(int32_t min_) {
min = min_; min = min_;
return *this; return *this;
} }
IntSliderOptions& Max(int32_t max_) { IntSliderOptions& Max(int32_t max_) {
max = max_; max = max_;
return *this; return *this;
} }
IntSliderOptions& DefaultValue(int32_t defaultValue_) { IntSliderOptions& DefaultValue(int32_t defaultValue_) {
defaultValue = defaultValue_; defaultValue = defaultValue_;
return *this; return *this;
} }
IntSliderOptions& ComponentAlignment(ComponentAlignments alignment_) { IntSliderOptions& ComponentAlignment(ComponentAlignments alignment_) {
alignment = alignment_; alignment = alignment_;
return *this; return *this;
} }
IntSliderOptions& LabelPosition(LabelPositions labelPosition_) { IntSliderOptions& LabelPosition(LabelPositions labelPosition_) {
labelPosition = labelPosition_; labelPosition = labelPosition_;
return *this; return *this;
} }
IntSliderOptions& Tooltip(const char* tooltip_) { IntSliderOptions& Tooltip(const char* tooltip_) {
WidgetOptions::tooltip = tooltip_; WidgetOptions::tooltip = tooltip_;
return *this; return *this;
} }
IntSliderOptions& Color(Colors color_) { IntSliderOptions& Color(Colors color_) {
color = color_; color = color_;
return *this; return *this;
} }
IntSliderOptions& Size(ImVec2 size_) { IntSliderOptions& Size(ImVec2 size_) {
size = size_; size = size_;
return *this; return *this;
} }
IntSliderOptions& Clamp(bool clamp_) { IntSliderOptions& Clamp(bool clamp_) {
clamp = clamp_; clamp = clamp_;
return *this; return *this;
@ -344,34 +376,42 @@ struct FloatSliderOptions : WidgetOptions {
showButtons = showButtons_; showButtons = showButtons_;
return *this; return *this;
} }
FloatSliderOptions& Format(const char* format_) { FloatSliderOptions& Format(const char* format_) {
format = format_; format = format_;
return *this; return *this;
} }
FloatSliderOptions& Step(float step_) { FloatSliderOptions& Step(float step_) {
step = step_; step = step_;
return *this; return *this;
} }
FloatSliderOptions& Min(float min_) { FloatSliderOptions& Min(float min_) {
min = min_; min = min_;
return *this; return *this;
} }
FloatSliderOptions& Max(float max_) { FloatSliderOptions& Max(float max_) {
max = max_; max = max_;
return *this; return *this;
} }
FloatSliderOptions& DefaultValue(float defaultValue_) { FloatSliderOptions& DefaultValue(float defaultValue_) {
defaultValue = defaultValue_; defaultValue = defaultValue_;
return *this; return *this;
} }
FloatSliderOptions& ComponentAlignment(ComponentAlignments alignment_) { FloatSliderOptions& ComponentAlignment(ComponentAlignments alignment_) {
alignment = alignment_; alignment = alignment_;
return *this; return *this;
} }
FloatSliderOptions& LabelPosition(LabelPositions labelPosition_) { FloatSliderOptions& LabelPosition(LabelPositions labelPosition_) {
labelPosition = labelPosition_; labelPosition = labelPosition_;
return *this; return *this;
} }
FloatSliderOptions& IsPercentage(bool isPercentage_ = true) { FloatSliderOptions& IsPercentage(bool isPercentage_ = true) {
isPercentage = isPercentage_; isPercentage = isPercentage_;
format = "%.0f%%"; format = "%.0f%%";
@ -379,18 +419,22 @@ struct FloatSliderOptions : WidgetOptions {
max = 1.0f; max = 1.0f;
return *this; return *this;
} }
FloatSliderOptions& Tooltip(const char* tooltip_) { FloatSliderOptions& Tooltip(const char* tooltip_) {
WidgetOptions::tooltip = tooltip_; WidgetOptions::tooltip = tooltip_;
return *this; return *this;
} }
FloatSliderOptions& Color(Colors color_) { FloatSliderOptions& Color(Colors color_) {
color = color_; color = color_;
return *this; return *this;
} }
FloatSliderOptions& Size(ImVec2 size_) { FloatSliderOptions& Size(ImVec2 size_) {
size = size_; size = size_;
return *this; return *this;
} }
FloatSliderOptions& Clamp(bool clamp_) { FloatSliderOptions& Clamp(bool clamp_) {
clamp = clamp_; clamp = clamp_;
return *this; return *this;
@ -406,14 +450,17 @@ struct RadioButtonsOptions : WidgetOptions {
buttonMap = buttonMap_; buttonMap = buttonMap_;
return *this; return *this;
} }
RadioButtonsOptions& Tooltip(const char* tooltip_) { RadioButtonsOptions& Tooltip(const char* tooltip_) {
WidgetOptions::tooltip = tooltip_; WidgetOptions::tooltip = tooltip_;
return *this; return *this;
} }
RadioButtonsOptions& Color(Colors color_) { RadioButtonsOptions& Color(Colors color_) {
color = color_; color = color_;
return *this; return *this;
} }
RadioButtonsOptions& DefaultIndex(int32_t defaultIndex_) { RadioButtonsOptions& DefaultIndex(int32_t defaultIndex_) {
defaultIndex = defaultIndex_; defaultIndex = defaultIndex_;
return *this; return *this;
@ -437,10 +484,12 @@ struct InputOptions : WidgetOptions {
WidgetOptions::tooltip = tooltip_; WidgetOptions::tooltip = tooltip_;
return *this; return *this;
} }
InputOptions& Color(Colors color_) { InputOptions& Color(Colors color_) {
color = color_; color = color_;
return *this; return *this;
} }
InputOptions& Size(ImVec2 size_) { InputOptions& Size(ImVec2 size_) {
size = size_; size = size_;
return *this; return *this;

View file

@ -1284,8 +1284,16 @@ void Actor_UpdatePos(Actor* actor) {
} }
void Actor_UpdateVelocityXZGravity(Actor* actor) { void Actor_UpdateVelocityXZGravity(Actor* actor) {
actor->velocity.x = Math_SinS(actor->world.rot.y) * actor->speedXZ; Player* player = GET_PLAYER(gPlayState);
actor->velocity.z = Math_CosS(actor->world.rot.y) * actor->speedXZ; uint8_t inCutscene = player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER ||
player->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE ||
player->stateFlags2 & PLAYER_STATE2_CRAWLING;
f32 speedModifier = 1.0f;
if (actor->id == ACTOR_PLAYER && !inCutscene) {
speedModifier = GameInteractor_MovementSpeedMultiplier();
}
actor->velocity.x = Math_SinS(actor->world.rot.y) * actor->speedXZ * speedModifier;
actor->velocity.z = Math_CosS(actor->world.rot.y) * actor->speedXZ * speedModifier;
actor->velocity.y += actor->gravity; actor->velocity.y += actor->gravity;
if (actor->velocity.y < actor->minVelocityY) { if (actor->velocity.y < actor->minVelocityY) {
@ -5047,8 +5055,8 @@ void Flags_SetRandomizerInf(RandomizerInf flag) {
*/ */
s32 previouslyOff = !Flags_GetRandomizerInf(flag); s32 previouslyOff = !Flags_GetRandomizerInf(flag);
gSaveContext.ship.randomizerInf[flag >> 4] |= (1 << (flag & 0xF));
if (previouslyOff) { if (previouslyOff) {
gSaveContext.ship.randomizerInf[flag >> 4] |= (1 << (flag & 0xF));
LUSLOG_INFO("RandomizerInf Flag Set - %#x", flag); LUSLOG_INFO("RandomizerInf Flag Set - %#x", flag);
GameInteractor_ExecuteOnFlagSet(FLAG_RANDOMIZER_INF, flag); GameInteractor_ExecuteOnFlagSet(FLAG_RANDOMIZER_INF, flag);
} }
@ -5068,8 +5076,8 @@ void Flags_UnsetRandomizerInf(RandomizerInf flag) {
*/ */
s32 previouslyOn = Flags_GetRandomizerInf(flag); s32 previouslyOn = Flags_GetRandomizerInf(flag);
gSaveContext.ship.randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF));
if (previouslyOn) { if (previouslyOn) {
gSaveContext.ship.randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF));
LUSLOG_INFO("RandomizerInf Flag Unset - %#x", flag); LUSLOG_INFO("RandomizerInf Flag Unset - %#x", flag);
GameInteractor_ExecuteOnFlagUnset(FLAG_RANDOMIZER_INF, flag); GameInteractor_ExecuteOnFlagUnset(FLAG_RANDOMIZER_INF, flag);
} }

View file

@ -813,7 +813,8 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
} }
} else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { } else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) {
if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT), if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS,
!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE),
RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) { RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) {
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE);
if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) { if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) {
@ -831,7 +832,8 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
} }
} else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { } else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) {
if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW), if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS,
!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE),
RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) { RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) {
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE);
if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) { if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) {

View file

@ -58,6 +58,11 @@ void EnAttackNiw_Init(Actor* thisx, PlayState* play) {
this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED; this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED;
this->actor.shape.rot.y = this->actor.world.rot.y = (Rand_ZeroOne() - 0.5f) * 60000.0f; this->actor.shape.rot.y = this->actor.world.rot.y = (Rand_ZeroOne() - 0.5f) * 60000.0f;
this->actionFunc = func_809B5670; this->actionFunc = func_809B5670;
if (CVarGetInteger("gCrowdControl", 0) &&
CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) {
Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, this, ACTORCAT_NPC);
}
} }
void EnAttackNiw_Destroy(Actor* thisx, PlayState* play) { void EnAttackNiw_Destroy(Actor* thisx, PlayState* play) {

View file

@ -7124,15 +7124,6 @@ void func_8083DFE0(Player* this, f32* arg1, s16* arg2) {
if (this->meleeWeaponState == 0) { if (this->meleeWeaponState == 0) {
float maxSpeed = R_RUN_SPEED_LIMIT / 100.0f; float maxSpeed = R_RUN_SPEED_LIMIT / 100.0f;
int32_t giSpeedModifier = GameInteractor_RunSpeedModifier();
if (giSpeedModifier != 0) {
if (giSpeedModifier > 0) {
maxSpeed *= giSpeedModifier;
} else {
maxSpeed /= abs(giSpeedModifier);
}
}
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) == BUNNY_HOOD_FAST_AND_JUMP && if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) == BUNNY_HOOD_FAST_AND_JUMP &&
this->currentMask == PLAYER_MASK_BUNNY) { this->currentMask == PLAYER_MASK_BUNNY) {
maxSpeed *= 1.5f; maxSpeed *= 1.5f;
@ -8873,14 +8864,6 @@ void Player_Action_80842180(Player* this, PlayState* play) {
Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_CURVED, play); Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_CURVED, play);
if (!func_8083C484(this, &sp2C, &sp2A)) { if (!func_8083C484(this, &sp2C, &sp2A)) {
int32_t giSpeedModifier = GameInteractor_RunSpeedModifier();
if (giSpeedModifier != 0) {
if (giSpeedModifier > 0) {
sp2C *= giSpeedModifier;
} else {
sp2C /= abs(giSpeedModifier);
}
}
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA &&
this->currentMask == PLAYER_MASK_BUNNY) { this->currentMask == PLAYER_MASK_BUNNY) {

View file

@ -124,7 +124,17 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) {
s16 pad2; s16 pad2;
s16 phi_s0_2; s16 phi_s0_2;
s16 sp208[3]; s16 sp208[3];
bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); if (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0)) {
if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) {
pauseCtx->stickRelX = -35;
} else if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) {
pauseCtx->stickRelX = 35;
} else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) {
pauseCtx->stickRelY = -35;
} else if (CHECK_BTN_ALL(input->press.button, BTN_DUP)) {
pauseCtx->stickRelY = 35;
}
}
OPEN_DISPS(gfxCtx); OPEN_DISPS(gfxCtx);
@ -140,7 +150,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) {
} else { } else {
phi_s3 = pauseCtx->cursorPoint[PAUSE_QUEST]; phi_s3 = pauseCtx->cursorPoint[PAUSE_QUEST];
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { if ((pauseCtx->stickRelX < -30)) {
phi_s0 = D_8082A1AC[phi_s3][2]; phi_s0 = D_8082A1AC[phi_s3][2];
if (phi_s0 == -3) { if (phi_s0 == -3) {
KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_LEFT); KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_LEFT);
@ -153,7 +163,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) {
phi_s0 = D_8082A1AC[phi_s0][2]; phi_s0 = D_8082A1AC[phi_s0][2];
} }
} }
} else if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) { } else if ((pauseCtx->stickRelX > 30)) {
phi_s0 = D_8082A1AC[phi_s3][3]; phi_s0 = D_8082A1AC[phi_s3][3];
if (phi_s0 == -2) { if (phi_s0 == -2) {
KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_RIGHT); KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_RIGHT);
@ -168,7 +178,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) {
} }
} }
if ((pauseCtx->stickRelY < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) { if ((pauseCtx->stickRelY < -30)) {
phi_s0 = D_8082A1AC[phi_s3][1]; phi_s0 = D_8082A1AC[phi_s3][1];
while (phi_s0 >= 0) { while (phi_s0 >= 0) {
if ((s16)KaleidoScope_UpdateQuestStatusPoint(pauseCtx, phi_s0) != 0) { if ((s16)KaleidoScope_UpdateQuestStatusPoint(pauseCtx, phi_s0) != 0) {
@ -176,7 +186,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) {
} }
phi_s0 = D_8082A1AC[phi_s0][1]; phi_s0 = D_8082A1AC[phi_s0][1];
} }
} else if ((pauseCtx->stickRelY > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) { } else if ((pauseCtx->stickRelY > 30)) {
phi_s0 = D_8082A1AC[phi_s3][0]; phi_s0 = D_8082A1AC[phi_s3][0];
while (phi_s0 >= 0) { while (phi_s0 >= 0) {
if ((s16)KaleidoScope_UpdateQuestStatusPoint(pauseCtx, phi_s0) != 0) { if ((s16)KaleidoScope_UpdateQuestStatusPoint(pauseCtx, phi_s0) != 0) {
@ -267,7 +277,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) {
} }
} }
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) { } else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) { if ((pauseCtx->stickRelX > 30)) {
pauseCtx->cursorPoint[PAUSE_QUEST] = 0x15; pauseCtx->cursorPoint[PAUSE_QUEST] = 0x15;
pauseCtx->nameDisplayTimer = 0; pauseCtx->nameDisplayTimer = 0;
pauseCtx->cursorSpecialPos = 0; pauseCtx->cursorSpecialPos = 0;
@ -285,7 +295,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) {
pauseCtx->cursorSlot[pauseCtx->pageIndex] = sp216; pauseCtx->cursorSlot[pauseCtx->pageIndex] = sp216;
} }
} else { } else {
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { if ((pauseCtx->stickRelX < -30)) {
pauseCtx->cursorPoint[PAUSE_QUEST] = 0; pauseCtx->cursorPoint[PAUSE_QUEST] = 0;
pauseCtx->nameDisplayTimer = 0; pauseCtx->nameDisplayTimer = 0;
pauseCtx->cursorSpecialPos = 0; pauseCtx->cursorSpecialPos = 0;