Merge branch 'develop' into ItemName

This commit is contained in:
Pepper0ni 2025-04-02 13:08:05 +01:00
commit 297e2def7f
889 changed files with 39918 additions and 35663 deletions

21
.github/workflows/clang-format.yml vendored Normal file
View file

@ -0,0 +1,21 @@
name: clang-format
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
clang-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Install clang-format
run: |
sudo apt-get update
sudo apt-get install -y clang-format-14
- name: Run clang-format
run: |
./run-clang-format.sh
git diff --exit-code

4
.gitignore vendored
View file

@ -452,3 +452,7 @@ _packages
soh/src/boot/build.c soh/src/boot/build.c
soh/properties.h soh/properties.h
# Tools
/clang-format
/clang-format.exe

48
run-clang-format.ps1 Normal file
View file

@ -0,0 +1,48 @@
Using Namespace System
$url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.6/LLVM-14.0.6-win64.exe"
$llvmInstallerPath = ".\LLVM-14.0.6-win64.exe"
$clangFormatFilePath = ".\clang-format.exe"
$requiredVersion = "clang-format version 14.0.6"
$currentVersion = ""
function Test-7ZipInstalled {
$sevenZipPath = "C:\Program Files\7-Zip\7z.exe"
return Test-Path $sevenZipPath -PathType Leaf
}
if (Test-Path $clangFormatFilePath) {
$currentVersion = & $clangFormatFilePath --version
if (-not ($currentVersion -eq $requiredVersion)) {
# Delete the existing file if the version is incorrect
Remove-Item $clangFormatFilePath -Force
}
}
if (-not (Test-Path $clangFormatFilePath) -or ($currentVersion -ne $requiredVersion)) {
if (-not (Test-7ZipInstalled)) {
Write-Host "7-Zip is not installed. Please install 7-Zip and run the script again."
exit
}
$wc = New-Object net.webclient
$wc.Downloadfile($url, $llvmInstallerPath)
$sevenZipPath = "C:\Program Files\7-Zip\7z.exe"
$specificFileInArchive = "bin\clang-format.exe"
& "$sevenZipPath" e $llvmInstallerPath $specificFileInArchive
Remove-Item $llvmInstallerPath -Force
}
$basePath = (Resolve-Path .).Path
$files = Get-ChildItem -Path $basePath\soh -Recurse -File `
| Where-Object { ($_.Extension -eq '.c' -or $_.Extension -eq '.cpp' -or `
($_.Extension -eq '.h' -and `
(-not ($_.FullName -like "*\soh\src\*" -or $_.FullName -like "*\soh\include\*")))) -and `
(-not ($_.FullName -like "*\soh\assets\*")) }
foreach ($file in $files) {
$relativePath = $file.FullName.Substring($basePath.Length + 1)
Write-Host "Formatting $relativePath"
.\clang-format.exe -i $file.FullName
}

29
run-clang-format.sh Executable file
View file

@ -0,0 +1,29 @@
# this line does quite a bit, so let's break it down
#
# find soh
# use "find" to look in the "soh" directory
# this ensures we don't try to format stuff in the submodules
#
# -type f
# only look for files
#
# -name "*.c" -o -name "*.cpp"
# find all .c and .cpp files
#
# -name "*.h" ! -path "soh/src/**.h" ! -path "soh/include/**.h"
# find all .h files that aren't in soh/src or soh/include
# this is because zret decomp only runs clang-format on c files
# https://github.com/zeldaret/mm/blob/b7e5468ca16315a7e322055eff3d97fe980bbc25/format.py#L182
#
# ! -path "soh/assets/*"
# asset headers are autogenerated, don't fight them
#
# | sed 's| |\\ |g'
# pipe the result of find into sed to
# ensure all the paths returned by find have spaces escaped
#
# | xargs clang-format-14 -i
# use xargs to take each path we've found
# and pass it as an argument to clang-format
find soh -type f \( -name "*.c" -o -name "*.cpp" -o \( -name "*.h" ! -path "soh/src/**.h" ! -path "soh/include/**.h" \) \) ! -path "soh/assets/*" | sed 's| |\\ |g' | xargs clang-format-14 -i

View file

@ -4,7 +4,6 @@
ActorDB* ActorDB::Instance; ActorDB* ActorDB::Instance;
#define DEFINE_ACTOR(name, _1, _2) extern "C" ActorInit name##_InitVars; #define DEFINE_ACTOR(name, _1, _2) extern "C" ActorInit name##_InitVars;
#define DEFINE_ACTOR_INTERNAL(name, _1, _2) extern "C" ActorInit name##_InitVars; #define DEFINE_ACTOR_INTERNAL(name, _1, _2) extern "C" ActorInit name##_InitVars;
#define DEFINE_ACTOR_UNSET(_0) #define DEFINE_ACTOR_UNSET(_0)
@ -464,7 +463,8 @@ static constexpr std::pair<u16, const char*> actorDescriptionData[] = {
{ ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" }, { ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" },
{ ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" }, { ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" },
}; };
static std::unordered_map<u16, const char*> actorDescriptions = std::unordered_map<u16, const char*>(std::begin(actorDescriptionData), std::end(actorDescriptionData)); static std::unordered_map<u16, const char*> actorDescriptions =
std::unordered_map<u16, const char*>(std::begin(actorDescriptionData), std::end(actorDescriptionData));
ActorDB::ActorDB() { ActorDB::ActorDB() {
db.reserve(ACTOR_NUMBER_MAX); // reserve size for all initial entries so we don't do it for each db.reserve(ACTOR_NUMBER_MAX); // reserve size for all initial entries so we don't do it for each
@ -475,7 +475,8 @@ ActorDB::ActorDB() {
// Adds an actor at the given index. The name must be unique. // Adds an actor at the given index. The name must be unique.
ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& desc, size_t index) { ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& desc, size_t index) {
assert(!nameTable.contains(name)); // TODO this should maybe throw instead. We'll need to think about error handling for mods that try to declare the same actor. assert(!nameTable.contains(name)); // TODO this should maybe throw instead. We'll need to think about error handling
// for mods that try to declare the same actor.
if (db.size() < (index + 1)) { if (db.size() < (index + 1)) {
db.resize(index + 1); db.resize(index + 1);
@ -513,7 +514,8 @@ ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& de
return entry; return entry;
} }
// Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the return Entry or RetrieveId to get it. // Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the return Entry or
// RetrieveId to get it.
ActorDB::Entry& ActorDB::AddEntry(const ActorDBInit& init) { ActorDB::Entry& ActorDB::AddEntry(const ActorDBInit& init) {
Entry& entry = AddEntry(init.name, init.desc, nextFreeId); Entry& entry = AddEntry(init.name, init.desc, nextFreeId);
@ -598,7 +600,8 @@ static ActorDBInit EnPartnerInit = {
"En_Partner", "En_Partner",
"Ivan", "Ivan",
ACTORCAT_ITEMACTION, ACTORCAT_ITEMACTION,
(ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED | ACTOR_FLAG_HOOKSHOT_PULLS_PLAYER | ACTOR_FLAG_CAN_PRESS_SWITCHES), (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED | ACTOR_FLAG_HOOKSHOT_PULLS_PLAYER |
ACTOR_FLAG_CAN_PRESS_SWITCHES),
OBJECT_GAMEPLAY_KEEP, OBJECT_GAMEPLAY_KEEP,
sizeof(EnPartner), sizeof(EnPartner),
(ActorFunc)EnPartner_Init, (ActorFunc)EnPartner_Init,

View file

@ -65,6 +65,7 @@ public:
static void AddBuiltInCustomActors(); static void AddBuiltInCustomActors();
int GetEntryCount(); int GetEntryCount();
private: private:
Entry& AddEntry(const std::string& name, const std::string& desc, size_t index); Entry& AddEntry(const std::string& name, const std::string& desc, size_t index);
Entry& AddEntry(const std::string& name, const std::string& desc, const ActorInit& init); Entry& AddEntry(const std::string& name, const std::string& desc, const ActorInit& init);

View file

@ -1,6 +1,5 @@
#include <libultraship/bridge.h> #include <libultraship/bridge.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View file

@ -16,10 +16,9 @@ static u16 sItemButtons[] = { BTN_B, BTN_CLEFT, BTN_CDOWN, BTN_CRIGHT, BTN_DUP,
void UseTunicBoots(Player* player, PlayState* play, Input* input) { void UseTunicBoots(Player* player, PlayState* play, Input* input) {
// Boots and tunics equip despite state // Boots and tunics equip despite state
if ( if (player->stateFlags1 & (PLAYER_STATE1_INPUT_DISABLED | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE |
player->stateFlags1 & (PLAYER_STATE1_INPUT_DISABLED | PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE | PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD) || PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD) ||
player->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING player->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING) {
) {
return; return;
} }
@ -40,7 +39,8 @@ void UseTunicBoots(Player* player, PlayState* play, Input* input) {
Inventory_ChangeEquipment(EQUIP_TYPE_BOOTS, bootsValue); Inventory_ChangeEquipment(EQUIP_TYPE_BOOTS, bootsValue);
} }
Player_SetEquipmentData(play, player); Player_SetEquipmentData(play, player);
func_808328EC(player, CUR_EQUIP_VALUE(EQUIP_TYPE_BOOTS) == EQUIP_VALUE_BOOTS_IRON ? NA_SE_PL_WALK_HEAVYBOOTS : NA_SE_PL_CHANGE_ARMS); func_808328EC(player, CUR_EQUIP_VALUE(EQUIP_TYPE_BOOTS) == EQUIP_VALUE_BOOTS_IRON ? NA_SE_PL_WALK_HEAVYBOOTS
: NA_SE_PL_CHANGE_ARMS);
} else { } else {
u16 tunicValue = item - ITEM_TUNIC_KOKIRI + 1; u16 tunicValue = item - ITEM_TUNIC_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == tunicValue) { if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) == tunicValue) {

View file

@ -30,7 +30,8 @@ void RegisterFreezeTime() {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnGameFrameUpdate>(hookId); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnGameFrameUpdate>(hookId);
hookId = 0; hookId = 0;
if (CVAR_FREEZE_TIME_VALUE) { if (CVAR_FREEZE_TIME_VALUE) {
hookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(OnGameFrameUpdateFreezeTime); hookId =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(OnGameFrameUpdateFreezeTime);
} else { } else {
CVarClear(CVAR_PREV_TIME_NAME); CVarClear(CVAR_PREV_TIME_NAME);
} }

View file

@ -15,10 +15,7 @@ extern s32 Flags_GetRandomizerInf(RandomizerInf flag);
#define CVAR_INFINITE_MONEY_VALUE CVarGetInteger(CVAR_INFINITE_MONEY_NAME, CVAR_INFINITE_MONEY_DEFAULT) #define CVAR_INFINITE_MONEY_VALUE CVarGetInteger(CVAR_INFINITE_MONEY_NAME, CVAR_INFINITE_MONEY_DEFAULT)
void OnGameFrameUpdateInfiniteMoney() { void OnGameFrameUpdateInfiniteMoney() {
if ( if (!GameInteractor::IsSaveLoaded(true) || (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))) {
!GameInteractor::IsSaveLoaded(true) ||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))
) {
return; return;
} }

View file

@ -7,7 +7,8 @@ extern "C" SaveContext gSaveContext;
#define CVAR_INFINITE_NAYRUS_LOVE_NAME CVAR_CHEAT("InfiniteNayru") #define CVAR_INFINITE_NAYRUS_LOVE_NAME CVAR_CHEAT("InfiniteNayru")
#define CVAR_INFINITE_NAYRUS_LOVE_DEFAULT 0 #define CVAR_INFINITE_NAYRUS_LOVE_DEFAULT 0
#define CVAR_INFINITE_NAYRUS_LOVE_VALUE CVarGetInteger(CVAR_INFINITE_NAYRUS_LOVE_NAME, CVAR_INFINITE_NAYRUS_LOVE_DEFAULT) #define CVAR_INFINITE_NAYRUS_LOVE_VALUE \
CVarGetInteger(CVAR_INFINITE_NAYRUS_LOVE_NAME, CVAR_INFINITE_NAYRUS_LOVE_DEFAULT)
void OnGameFrameUpdateInfiniteNayrusLove() { void OnGameFrameUpdateInfiniteNayrusLove() {
if (!GameInteractor::IsSaveLoaded(true)) { if (!GameInteractor::IsSaveLoaded(true)) {

View file

@ -36,23 +36,19 @@ static int statusTimer = -1;
static int eventTimer = -1; static int eventTimer = -1;
const char* altTrapTypeCvars[] = { const char* altTrapTypeCvars[] = {
CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"),
CVAR_ENHANCEMENT("ExtraTraps.Burn"), CVAR_ENHANCEMENT("ExtraTraps.Shock"), CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
CVAR_ENHANCEMENT("ExtraTraps.Shock"), CVAR_ENHANCEMENT("ExtraTraps.Speed"), CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
CVAR_ENHANCEMENT("ExtraTraps.Knockback"), CVAR_ENHANCEMENT("ExtraTraps.Void"), CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
CVAR_ENHANCEMENT("ExtraTraps.Speed"), CVAR_ENHANCEMENT("ExtraTraps.Kill"), CVAR_ENHANCEMENT("ExtraTraps.Teleport"),
CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
CVAR_ENHANCEMENT("ExtraTraps.Void"),
CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
CVAR_ENHANCEMENT("ExtraTraps.Kill"),
CVAR_ENHANCEMENT("ExtraTraps.Teleport"),
}; };
std::vector<AltTrapType> getEnabledAddTraps() { std::vector<AltTrapType> getEnabledAddTraps() {
std::vector<AltTrapType> enabledAddTraps; std::vector<AltTrapType> enabledAddTraps;
for (int i = 0; i < ADD_TRAP_MAX; i++) { for (int i = 0; i < ADD_TRAP_MAX; i++) {
if (CVarGetInteger(altTrapTypeCvars[i], 0)) { if (CVarGetInteger(altTrapTypeCvars[i], 0)) {
if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE && (i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) { if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE &&
(i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) {
continue; // don't add void or teleport if you're holding the fishing pole, as this causes issues continue; // don't add void or teleport if you're holding the fishing pole, as this causes issues
} }
enabledAddTraps.push_back(static_cast<AltTrapType>(i)); enabledAddTraps.push_back(static_cast<AltTrapType>(i));
@ -65,7 +61,8 @@ std::vector<AltTrapType> getEnabledAddTraps () {
}; };
static void RollRandomTrap(uint32_t seed) { static void RollRandomTrap(uint32_t seed) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt); uint32_t finalSeed =
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed); Random_Init(finalSeed);
roll = RandomElement(getEnabledAddTraps()); roll = RandomElement(getEnabledAddTraps());
@ -83,7 +80,8 @@ static void RollRandomTrap(uint32_t seed) {
eventTimer = 3; eventTimer = 3;
break; break;
case ADD_SPEED_TRAP: case ADD_SPEED_TRAP:
Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
GameInteractor::State::RunSpeedModifier = -2; GameInteractor::State::RunSpeedModifier = -2;
statusTimer = 200; statusTimer = 200;
Notification::Emit({ .message = "Speed Decreased!" }); Notification::Emit({ .message = "Speed Decreased!" });
@ -92,7 +90,8 @@ static void RollRandomTrap(uint32_t seed) {
eventTimer = 3; eventTimer = 3;
break; break;
case ADD_VOID_TRAP: case ADD_VOID_TRAP:
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
eventTimer = 3; eventTimer = 3;
break; break;
case ADD_AMMO_TRAP: case ADD_AMMO_TRAP:
@ -133,7 +132,8 @@ static void OnPlayerUpdate() {
AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5; AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5; AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5;
AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5; AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5;
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break; break;
case ADD_TELEPORT_TRAP: { case ADD_TELEPORT_TRAP: {
int entrance; int entrance;
@ -199,5 +199,3 @@ void RegisterExtraTraps() {
} }
static RegisterShipInitFunc initFunc(RegisterExtraTraps, { CVAR_EXTRA_TRAPS_NAME }); static RegisterShipInitFunc initFunc(RegisterExtraTraps, { CVAR_EXTRA_TRAPS_NAME });

View file

@ -39,8 +39,7 @@ std::array<std::string, LANGUAGE_MAX> RandomizerSettingsMenuText[RSM_MAX] = {
// French // French
"Génération en cours...", "Génération en cours...",
}, },
{ { // English
// English
"No randomizer seed loaded.\nPlease generate one first" "No randomizer seed loaded.\nPlease generate one first"
#if defined(__WIIU__) || defined(__SWITCH__) #if defined(__WIIU__) || defined(__SWITCH__)
".", ".",

View file

@ -3,10 +3,14 @@
#include "soh/cvar_prefixes.h" #include "soh/cvar_prefixes.h"
#include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/enhancementTypes.h"
#define PRESET_ENTRY_S32(cvar, value) { cvar, PRESET_ENTRY_TYPE_S32, value } #define PRESET_ENTRY_S32(cvar, value) \
#define PRESET_ENTRY_FLOAT(cvar, value) { cvar, PRESET_ENTRY_TYPE_FLOAT, value } { cvar, PRESET_ENTRY_TYPE_S32, value }
#define PRESET_ENTRY_STRING(cvar, value) { cvar, PRESET_ENTRY_TYPE_STRING, value } #define PRESET_ENTRY_FLOAT(cvar, value) \
#define PRESET_ENTRY_CPP_STRING(cvar, value) { cvar, PRESET_ENTRY_TYPE_CPP_STRING, value } { cvar, PRESET_ENTRY_TYPE_FLOAT, value }
#define PRESET_ENTRY_STRING(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_STRING, value }
#define PRESET_ENTRY_CPP_STRING(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_CPP_STRING, value }
// TODO: Ideally everything in this file will come from one/many JSON files // TODO: Ideally everything in this file will come from one/many JSON files
@ -20,16 +24,14 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
// Skips & Speed-ups // Skips & Speed-ups
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
// Graphics // Graphics
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1),
@ -41,26 +43,20 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
// Fixes // Fixes
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
// Difficulty // Difficulty
// NONE // NONE
@ -78,42 +74,33 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
const std::vector<PresetEntry> enhancedPresetEntries = { const std::vector<PresetEntry> enhancedPresetEntries = {
// Quality of Life // Quality of Life
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseWarp"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseWarp"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableCritWiggle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableCritWiggle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 1),
// Skips & Speed-ups // Skips & Speed-ups
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SlowTextSpeed"), 5), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SlowTextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CrawlSpeed"), 2),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), PRESET_ENTRY_FLOAT(CVAR_ENHANCEMENT("MweepSpeed"), 5.0f), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CrawlSpeed"), 2),
PRESET_ENTRY_FLOAT(CVAR_ENHANCEMENT("MweepSpeed"), 5.0f),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InstantScarecrow"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkulltulaFreeze"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
// Graphics // Graphics
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseMenuAnimatedLink"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseMenuAnimatedLink"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ToTMedallionsColors"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ToTMedallionsColors"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterAmmoRendering"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterAmmoRendering"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1),
@ -125,49 +112,36 @@ const std::vector<PresetEntry> enhancedPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DpadNoDropOcarinaInput"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastOcarinaPlayback"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PersistentMasks"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PersistentMasks"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableFirstPersonChus"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableFirstPersonChus"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterBombchuShopping"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterBombchuShopping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterFarore"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterFarore"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1),
// Fixes // Fixes
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DekuNutUpgradeFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixGrokenGiantsKnife"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixMenuLR"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("HoverFishing"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickBongoKill"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("N64WeirdFrames"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BombchusOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickPutaway"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("QuickBongoKill"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 1),
// Difficulty // Difficulty
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnableBombchuDrops"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnableBombchuDrops"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1),
// Minigames // Minigames
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 1),
@ -502,15 +476,12 @@ const std::vector<PresetEntry> randomizerAdvancedPresetEntries = {
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SheikLAHint"), 0), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SheikLAHint"), 0),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SariaHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SariaHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FrogsHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FrogsHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MerchantText"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MerchantText"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),

View file

@ -47,7 +47,8 @@ void DrawPresetSelector(PresetType presetTypeId) {
const PresetDefinition selectedPresetDef = presetTypeDef.presets.at(selectedPresetId); const PresetDefinition selectedPresetDef = presetTypeDef.presets.at(selectedPresetId);
std::string comboboxTooltip = ""; std::string comboboxTooltip = "";
for (auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter) { for (auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter) {
if (iter->first != 0) comboboxTooltip += "\n\n"; if (iter->first != 0)
comboboxTooltip += "\n\n";
comboboxTooltip += std::string(iter->second.label) + " - " + std::string(iter->second.description); comboboxTooltip += std::string(iter->second.label) + " - " + std::string(iter->second.description);
} }

View file

@ -33,10 +33,13 @@ void OnEnMThunderInitReplaceUpdateWithCustom(void* thunder) {
#define CVAR_REMOVESPINATTACKDARKNESS_NAME CVAR_ENHANCEMENT("RemoveSpinAttackDarkness") #define CVAR_REMOVESPINATTACKDARKNESS_NAME CVAR_ENHANCEMENT("RemoveSpinAttackDarkness")
#define CVAR_REMOVESPINATTACKDARKNESS_DEFAULT 0 #define CVAR_REMOVESPINATTACKDARKNESS_DEFAULT 0
#define CVAR_REMOVESPINATTACKDARKNESS_VALUE CVarGetInteger(CVAR_REMOVESPINATTACKDARKNESS_NAME, CVAR_REMOVESPINATTACKDARKNESS_DEFAULT) #define CVAR_REMOVESPINATTACKDARKNESS_VALUE \
CVarGetInteger(CVAR_REMOVESPINATTACKDARKNESS_NAME, CVAR_REMOVESPINATTACKDARKNESS_DEFAULT)
void RegisterCustomEnMThunderUpdate() { void RegisterCustomEnMThunderUpdate() {
COND_ID_HOOK(OnActorInit, ACTOR_EN_M_THUNDER, CVAR_REMOVESPINATTACKDARKNESS_VALUE != CVAR_REMOVESPINATTACKDARKNESS_DEFAULT, OnEnMThunderInitReplaceUpdateWithCustom); COND_ID_HOOK(OnActorInit, ACTOR_EN_M_THUNDER,
CVAR_REMOVESPINATTACKDARKNESS_VALUE != CVAR_REMOVESPINATTACKDARKNESS_DEFAULT,
OnEnMThunderInitReplaceUpdateWithCustom);
} }
static RegisterShipInitFunc initFunc(RegisterCustomEnMThunderUpdate, { CVAR_REMOVESPINATTACKDARKNESS_NAME }); static RegisterShipInitFunc initFunc(RegisterCustomEnMThunderUpdate, { CVAR_REMOVESPINATTACKDARKNESS_NAME });

View file

@ -100,9 +100,11 @@ void HandleRBAInventoryQuestItems(uint8_t itemToPutInBottle) {
auto itemOnCRight = gSaveContext.equips.buttonItems[3]; auto itemOnCRight = gSaveContext.equips.buttonItems[3];
if (itemOnCRight == ITEM_ODD_MUSHROOM) { if (itemOnCRight == ITEM_ODD_MUSHROOM) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 24) | (gSaveContext.inventory.questItems & 0x00FFFFFF); gSaveContext.inventory.questItems =
(itemToPutInBottle << 24) | (gSaveContext.inventory.questItems & 0x00FFFFFF);
} else if (itemOnCRight == ITEM_ODD_POTION) { } else if (itemOnCRight == ITEM_ODD_POTION) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 16) | (gSaveContext.inventory.questItems & 0xFF00FFFF); gSaveContext.inventory.questItems =
(itemToPutInBottle << 16) | (gSaveContext.inventory.questItems & 0xFF00FFFF);
} else if (itemOnCRight == ITEM_SAW) { } else if (itemOnCRight == ITEM_SAW) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 8) | (gSaveContext.inventory.questItems & 0xFFFF00FF); gSaveContext.inventory.questItems = (itemToPutInBottle << 8) | (gSaveContext.inventory.questItems & 0xFFFF00FF);
} else if (itemOnCRight == ITEM_SWORD_BROKEN) { } else if (itemOnCRight == ITEM_SWORD_BROKEN) {
@ -265,88 +267,115 @@ void HandleRBASceneFlags(uint8_t itemToPutInBottle) {
u32 scene = offset / sizeof(SavedSceneFlags); u32 scene = offset / sizeof(SavedSceneFlags);
switch (offset % sizeof(SavedSceneFlags)) { switch (offset % sizeof(SavedSceneFlags)) {
case 0: case 0:
gSaveContext.sceneFlags[scene].chest = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].chest & 0x00FFFFFF); gSaveContext.sceneFlags[scene].chest =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].chest & 0x00FFFFFF);
break; break;
case 1: case 1:
gSaveContext.sceneFlags[scene].chest = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].chest & 0xFF00FFFF); gSaveContext.sceneFlags[scene].chest =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].chest & 0xFF00FFFF);
break; break;
case 2: case 2:
gSaveContext.sceneFlags[scene].chest = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].chest & 0xFFFF00FF); gSaveContext.sceneFlags[scene].chest =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].chest & 0xFFFF00FF);
break; break;
case 3: case 3:
gSaveContext.sceneFlags[scene].chest = itemToPutInBottle | (gSaveContext.sceneFlags[scene].chest & 0xFFFFFF00); gSaveContext.sceneFlags[scene].chest =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].chest & 0xFFFFFF00);
break; break;
case 4: case 4:
gSaveContext.sceneFlags[scene].swch = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].swch & 0x00FFFFFF); gSaveContext.sceneFlags[scene].swch =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].swch & 0x00FFFFFF);
break; break;
case 5: case 5:
gSaveContext.sceneFlags[scene].swch = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].swch & 0xFF00FFFF); gSaveContext.sceneFlags[scene].swch =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].swch & 0xFF00FFFF);
break; break;
case 6: case 6:
gSaveContext.sceneFlags[scene].swch = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].swch & 0xFFFF00FF); gSaveContext.sceneFlags[scene].swch =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].swch & 0xFFFF00FF);
break; break;
case 7: case 7:
gSaveContext.sceneFlags[scene].swch = itemToPutInBottle | (gSaveContext.sceneFlags[scene].swch & 0xFFFFFF00); gSaveContext.sceneFlags[scene].swch =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].swch & 0xFFFFFF00);
break; break;
case 8: case 8:
gSaveContext.sceneFlags[scene].clear = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].clear & 0x00FFFFFF); gSaveContext.sceneFlags[scene].clear =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].clear & 0x00FFFFFF);
break; break;
case 9: case 9:
gSaveContext.sceneFlags[scene].clear = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].clear & 0xFF00FFFF); gSaveContext.sceneFlags[scene].clear =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].clear & 0xFF00FFFF);
break; break;
case 10: case 10:
gSaveContext.sceneFlags[scene].clear = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].clear & 0xFFFF00FF); gSaveContext.sceneFlags[scene].clear =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].clear & 0xFFFF00FF);
break; break;
case 11: case 11:
gSaveContext.sceneFlags[scene].clear = itemToPutInBottle | (gSaveContext.sceneFlags[scene].clear & 0xFFFFFF00); gSaveContext.sceneFlags[scene].clear =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].clear & 0xFFFFFF00);
break; break;
case 12: case 12:
gSaveContext.sceneFlags[scene].collect = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].collect & 0x00FFFFFF); gSaveContext.sceneFlags[scene].collect =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].collect & 0x00FFFFFF);
break; break;
case 13: case 13:
gSaveContext.sceneFlags[scene].collect = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].collect & 0xFF00FFFF); gSaveContext.sceneFlags[scene].collect =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].collect & 0xFF00FFFF);
break; break;
case 14: case 14:
gSaveContext.sceneFlags[scene].collect = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].collect & 0xFFFF00FF); gSaveContext.sceneFlags[scene].collect =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].collect & 0xFFFF00FF);
break; break;
case 15: case 15:
gSaveContext.sceneFlags[scene].collect = itemToPutInBottle | (gSaveContext.sceneFlags[scene].collect & 0xFFFFFF00); gSaveContext.sceneFlags[scene].collect =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].collect & 0xFFFFFF00);
break; break;
case 16: case 16:
gSaveContext.sceneFlags[scene].unk = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].unk & 0x00FFFFFF); gSaveContext.sceneFlags[scene].unk =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].unk & 0x00FFFFFF);
break; break;
case 17: case 17:
gSaveContext.sceneFlags[scene].unk = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].unk & 0xFF00FFFF); gSaveContext.sceneFlags[scene].unk =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].unk & 0xFF00FFFF);
break; break;
case 18: case 18:
gSaveContext.sceneFlags[scene].unk = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].unk & 0xFFFF00FF); gSaveContext.sceneFlags[scene].unk =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].unk & 0xFFFF00FF);
break; break;
case 19: case 19:
gSaveContext.sceneFlags[scene].unk = itemToPutInBottle | (gSaveContext.sceneFlags[scene].unk & 0xFFFFFF00); gSaveContext.sceneFlags[scene].unk = itemToPutInBottle | (gSaveContext.sceneFlags[scene].unk & 0xFFFFFF00);
break; break;
case 20: case 20:
gSaveContext.sceneFlags[scene].rooms = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].rooms & 0x00FFFFFF); gSaveContext.sceneFlags[scene].rooms =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].rooms & 0x00FFFFFF);
break; break;
case 21: case 21:
gSaveContext.sceneFlags[scene].rooms = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].rooms & 0xFF00FFFF); gSaveContext.sceneFlags[scene].rooms =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].rooms & 0xFF00FFFF);
break; break;
case 22: case 22:
gSaveContext.sceneFlags[scene].rooms = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].rooms & 0xFFFF00FF); gSaveContext.sceneFlags[scene].rooms =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].rooms & 0xFFFF00FF);
break; break;
case 23: case 23:
gSaveContext.sceneFlags[scene].rooms = itemToPutInBottle | (gSaveContext.sceneFlags[scene].rooms & 0xFFFFFF00); gSaveContext.sceneFlags[scene].rooms =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].rooms & 0xFFFFFF00);
break; break;
case 24: case 24:
gSaveContext.sceneFlags[scene].floors = (itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].floors & 0x00FFFFFF); gSaveContext.sceneFlags[scene].floors =
(itemToPutInBottle << 24) | (gSaveContext.sceneFlags[scene].floors & 0x00FFFFFF);
break; break;
case 25: case 25:
gSaveContext.sceneFlags[scene].floors = (itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].floors & 0xFF00FFFF); gSaveContext.sceneFlags[scene].floors =
(itemToPutInBottle << 16) | (gSaveContext.sceneFlags[scene].floors & 0xFF00FFFF);
break; break;
case 26: case 26:
gSaveContext.sceneFlags[scene].floors = (itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].floors & 0xFFFF00FF); gSaveContext.sceneFlags[scene].floors =
(itemToPutInBottle << 8) | (gSaveContext.sceneFlags[scene].floors & 0xFFFF00FF);
break; break;
case 27: case 27:
gSaveContext.sceneFlags[scene].floors = itemToPutInBottle | (gSaveContext.sceneFlags[scene].floors & 0xFFFFFF00); gSaveContext.sceneFlags[scene].floors =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].floors & 0xFFFFFF00);
break; break;
} }
} }

View file

@ -31,8 +31,9 @@ void RegisterPauseBufferInputs() {
COND_VB_SHOULD(VB_KALEIDO_UNPAUSE_CLOSE, CVAR_BUFFER_VALUE || CVAR_INCLUDE_VALUE, { COND_VB_SHOULD(VB_KALEIDO_UNPAUSE_CLOSE, CVAR_BUFFER_VALUE || CVAR_INCLUDE_VALUE, {
Input* input = &gPlayState->state.input[0]; Input* input = &gPlayState->state.input[0];
// STEP #3: If the user opts to include held inputs in the buffer window, store the currnently held inputs, minus // STEP #3: If the user opts to include held inputs in the buffer window, store the currnently held inputs,
// the held inputs when the pause menu was opened. This only applies to the first frame of the buffer window // minus the held inputs when the pause menu was opened. This only applies to the first frame of the buffer
// window
if (CVAR_INCLUDE_VALUE && inputBufferTimer == 0) { if (CVAR_INCLUDE_VALUE && inputBufferTimer == 0) {
pauseInputs |= input->cur.button & ~prePauseInputs; pauseInputs |= input->cur.button & ~prePauseInputs;
prePauseInputs = 0; prePauseInputs = 0;
@ -63,9 +64,8 @@ void RegisterPauseBufferInputs() {
} }
// STEP #2: The unpause process has begun, so let's reset the input buffer timer // STEP #2: The unpause process has begun, so let's reset the input buffer timer
if (pauseCtx->state == PAUSE_STATE_UNPAUSE_SETUP || ( if (pauseCtx->state == PAUSE_STATE_UNPAUSE_SETUP ||
pauseCtx->state == PAUSE_STATE_SAVEPROMPT && (pauseCtx->unk_1EC == 2 || pauseCtx->unk_1EC == 5) (pauseCtx->state == PAUSE_STATE_SAVEPROMPT && (pauseCtx->unk_1EC == 2 || pauseCtx->unk_1EC == 5))) {
)) {
inputBufferTimer = 0; inputBufferTimer = 0;
} }

View file

@ -247,13 +247,17 @@ static void TimeDisplayInitTimers() {
} }
void TimeDisplayWindow::InitElement() { void TimeDisplayWindow::InitElement() {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("GAMEPLAY_TIMER", gClockIconTex, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("GAMEPLAY_TIMER", gClockIconTex,
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("DAY_TIME_TIMER", gSunIconTex, ImVec4(1, 1, 1, 1)); ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NIGHT_TIME_TIMER", gMoonIconTex, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("DAY_TIME_TIMER", gSunIconTex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NIGHT_TIME_TIMER", gMoonIconTex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NAVI_TIMER", gNaviIconTex, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NAVI_TIMER", gNaviIconTex, ImVec4(1, 1, 1, 1));
for (auto& load : digitList) { for (auto& load : digitList) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(load.first.c_str(), load.second, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(load.first.c_str(), load.second,
ImVec4(1, 1, 1, 1));
} }
TimeDisplayInitSettings(); TimeDisplayInitSettings();

View file

@ -20,16 +20,16 @@ void FasterHeavyBlockLift_Register() {
REGISTER_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, { REGISTER_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, {
Actor* actor = va_arg(args, Actor*); Actor* actor = va_arg(args, Actor*);
if ( if (actor->id == ACTOR_BG_HEAVY_BLOCK &&
actor->id == ACTOR_BG_HEAVY_BLOCK && (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
(CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO))) {
) {
*should = false; *should = false;
} }
}); });
REGISTER_VB_SHOULD(VB_FREEZE_LINK_FOR_BLOCK_THROW, { REGISTER_VB_SHOULD(VB_FREEZE_LINK_FOR_BLOCK_THROW, {
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
*should = false; *should = false;
} }
}); });
@ -42,7 +42,8 @@ void FasterHeavyBlockLift_Register() {
// Same actor is used for small and large silver rocks, use actor params to identify large ones // Same actor is used for small and large silver rocks, use actor params to identify large ones
bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1; bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1;
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) && (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) { if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) &&
(isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) {
*should = false; *should = false;
LinkAnimation_PlayOnceSetSpeed(gPlayState, &player->skelAnime, anim, 5.0f); LinkAnimation_PlayOnceSetSpeed(gPlayState, &player->skelAnime, anim, 5.0f);
} }

View file

@ -14,7 +14,8 @@ extern "C" {
void FasterRupeeAccumulator_Register() { void FasterRupeeAccumulator_Register() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnInterfaceUpdate>([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnInterfaceUpdate>([]() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 0)) return; if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 0))
return;
if (gSaveContext.rupeeAccumulator == 0) { if (gSaveContext.rupeeAccumulator == 0) {
return; return;

View file

@ -38,15 +38,18 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP; gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Dodongo's Cavern Blue warp // Dodongo's Cavern Blue warp
} else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT && gSaveContext.cutsceneIndex == 0xFFF1) { } else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT &&
gSaveContext.cutsceneIndex == 0xFFF1) {
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP; gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Jabu Jabu's Blue warp // Jabu Jabu's Blue warp
} else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP && gSaveContext.cutsceneIndex == 0xFFF0) { } else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP &&
gSaveContext.cutsceneIndex == 0xFFF0) {
gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP; gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Forest Temple Blue warp // Forest Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) { } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) {
// Normally set in the blue warp cutscene // Normally set in the blue warp cutscene
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT);
@ -58,14 +61,16 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Fire Temple Blue warp // Fire Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE && gSaveContext.cutsceneIndex == 0xFFF3) { } else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE &&
gSaveContext.cutsceneIndex == 0xFFF3) {
// Normally set in the blue warp cutscene // Normally set in the blue warp cutscene
Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED); Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED);
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP; gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Water Temple Blue warp // Water Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) { } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) {
// Normally set in the blue warp cutscene // Normally set in the blue warp cutscene
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800; gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800;
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER);
@ -73,11 +78,13 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP; gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Spirit Temple Blue warp // Spirit Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) { } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) {
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP; gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
// Shadow Temple Blue warp // Shadow Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) { } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) {
gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP; gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true; isBlueWarpCutscene = true;
} }
@ -92,7 +99,8 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
gSaveContext.cutsceneIndex = 0; gSaveContext.cutsceneIndex = 0;
} }
// This is outside the above condition because we want to handle both first and following visits to the blue warp // This is outside the above condition because we want to handle both first and following visits to the blue
// warp
if (sEnteredBlueWarp && overrideBlueWarpDestinations) { if (sEnteredBlueWarp && overrideBlueWarpDestinations) {
Entrance_OverrideBlueWarp(); Entrance_OverrideBlueWarp();
} }
@ -142,31 +150,35 @@ void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) {
void SkipBlueWarp_OnActorUpdate(void* actorPtr) { void SkipBlueWarp_OnActorUpdate(void* actorPtr) {
EnKo* enKo = static_cast<EnKo*>(actorPtr); EnKo* enKo = static_cast<EnKo*>(actorPtr);
if ( if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && enKo->actionFunc == func_80A995CC &&
(enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
enKo->actionFunc == func_80A995CC &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)
) {
enKo->actionFunc = EnKo_MoveWhenReady; enKo->actionFunc = EnKo_MoveWhenReady;
} }
} }
/** /**
* This will ensure that the Deku Tree Sprout considers the Forest Temple finished when you skip the blue warp cutscene. * This will ensure that the Deku Tree Sprout considers the Forest Temple finished when you skip the blue warp cutscene.
* Typically this checks for if you have the medallion, and when skipping the cutscene at this point you don't have it yet. * Typically this checks for if you have the medallion, and when skipping the cutscene at this point you don't have it
* yet.
*/ */
void SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished(GIVanillaBehavior _, bool* should, va_list originalArgs) { void SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished(GIVanillaBehavior _, bool* should, va_list originalArgs) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP && gSaveContext.cutsceneIndex == 0xFFF1) { if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP &&
gSaveContext.cutsceneIndex == 0xFFF1) {
*should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
} }
} }
} }
void SkipBlueWarp_Register() { void SkipBlueWarp_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO, SkipBlueWarp_OnActorUpdate); GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO,
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS); SkipBlueWarp_OnActorUpdate);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS); GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished); VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_GIVE_ITEM_FROM_BLUE_WARP, SkipBlueWarp_ShouldGiveItem); GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_GIVE_ITEM_FROM_BLUE_WARP,
SkipBlueWarp_ShouldGiveItem);
} }

View file

@ -14,7 +14,8 @@ void SkipDekuTreeIntro_Register() {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
BgTreemouth* treeMouth = va_arg(args, BgTreemouth*); BgTreemouth* treeMouth = va_arg(args, BgTreemouth*);
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
BgTreemouth_SetupAction(treeMouth, func_808BC6F8); BgTreemouth_SetupAction(treeMouth, func_808BC6F8);
*should = false; *should = false;
} }

View file

@ -11,11 +11,13 @@ extern "C" {
void SkipLostWoodsBridge_Register() { void SkipLostWoodsBridge_Register() {
/** /**
* This skips the cutscene where you speak to Saria on the bridge in Lost Woods, where she gives you the Fairy Ocarina. * This skips the cutscene where you speak to Saria on the bridge in Lost Woods, where she gives you the Fairy
* Ocarina.
*/ */
REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, { REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_BRIDGE_EAST_EXIT) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_BRIDGE_EAST_EXIT) &&
!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE);
if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true)) { if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true)) {
Item_Give(gPlayState, ITEM_OCARINA_FAIRY); Item_Give(gPlayState, ITEM_OCARINA_FAIRY);
@ -26,8 +28,9 @@ void SkipLostWoodsBridge_Register() {
}); });
/** /**
* While we could rely on the Item_Give that's normally called (and that we have above), it's not very clear to the player * While we could rely on the Item_Give that's normally called (and that we have above), it's not very clear to the
* that they received the item when skipping the cutscene, so we'll prevent it, and queue it up to be given instead. * player that they received the item when skipping the cutscene, so we'll prevent it, and queue it up to be given
* instead.
*/ */
REGISTER_VB_SHOULD(VB_GIVE_ITEM_FAIRY_OCARINA, { REGISTER_VB_SHOULD(VB_GIVE_ITEM_FAIRY_OCARINA, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {

View file

@ -21,7 +21,8 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
Audio_PlayFanfare(NA_BGM_APPEAR); Audio_PlayFanfare(NA_BGM_APPEAR);
enZl4->csState = 8; // ZL4_CS_PLAN enZl4->csState = 8; // ZL4_CS_PLAN
} else { } else {
Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f, EnZl4_GiveItemTextId, func_80B5B9B0); Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f,
EnZl4_GiveItemTextId, func_80B5B9B0);
func_80B5BB78(enZl4, play); func_80B5BB78(enZl4, play);
if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) { if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) {
@ -34,12 +35,14 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
void SkipToGivingZeldasLetter_OnActorInit(void* actorPtr) { void SkipToGivingZeldasLetter_OnActorInit(void* actorPtr) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
EnZl4* enZl4 = static_cast<EnZl4*>(actorPtr); EnZl4* enZl4 = static_cast<EnZl4*>(actorPtr);
if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return; if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0)
return;
enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter; enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter;
} }
} }
void SkipToGivingZeldasLetter_Register() { void SkipToGivingZeldasLetter_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_ZL4, SkipToGivingZeldasLetter_OnActorInit); GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_ZL4,
SkipToGivingZeldasLetter_OnActorInit);
} }

View file

@ -46,12 +46,10 @@ void SkipZeldaFleeingCastle_OnActorUpdate(void* actorPtr) {
void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) { void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) {
Actor* actor = static_cast<Actor*>(actorPtr); Actor* actor = static_cast<Actor*>(actorPtr);
if ( if (actor->params == 3 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
actor->params == 3 &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)
) {
framesSinceSpawn = 0; framesSinceSpawn = 0;
itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr<GameInteractor::OnActorUpdate>((uintptr_t)actorPtr, SkipZeldaFleeingCastle_OnActorUpdate); itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr<GameInteractor::OnActorUpdate>(
(uintptr_t)actorPtr, SkipZeldaFleeingCastle_OnActorUpdate);
sceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) { sceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
GameInteractor::Instance->UnregisterGameHookForPtr<GameInteractor::OnActorUpdate>(itemOcarinaUpdateHook); GameInteractor::Instance->UnregisterGameHookForPtr<GameInteractor::OnActorUpdate>(itemOcarinaUpdateHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(sceneInitHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(sceneInitHook);
@ -62,6 +60,8 @@ void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) {
} }
void SkipZeldaFleeingCastle_Register() { void SkipZeldaFleeingCastle_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_ITEM_OCARINA, SkipZeldaFleeingCastle_OnActorInit); GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_ITEM_OCARINA,
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_TRANSITION_CS, SkipZeldaFleeingCastle_ShouldPlayTransitionCS); SkipZeldaFleeingCastle_OnActorInit);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_TRANSITION_CS, SkipZeldaFleeingCastle_ShouldPlayTransitionCS);
} }

View file

@ -10,7 +10,8 @@ extern "C" {
* Adjusts the behavior of the elevator to start near the bottom if you are entering the room from the bottom * Adjusts the behavior of the elevator to start near the bottom if you are entering the room from the bottom
*/ */
void MoveJabuJabuElevator_Register() { void MoveJabuJabuElevator_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_BG_BDAN_OBJECTS, [](void* actorRef) { GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(
ACTOR_BG_BDAN_OBJECTS, [](void* actorRef) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
BgBdanObjects* bgBdanObjects = static_cast<BgBdanObjects*>(actorRef); BgBdanObjects* bgBdanObjects = static_cast<BgBdanObjects*>(actorRef);

View file

@ -17,13 +17,10 @@ extern "C" {
*/ */
void MoveMidoInKokiriForest_Register() { void MoveMidoInKokiriForest_Register() {
REGISTER_VB_SHOULD(VB_MOVE_MIDO_IN_KOKIRI_FOREST, { REGISTER_VB_SHOULD(VB_MOVE_MIDO_IN_KOKIRI_FOREST, {
if ( if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) && (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && gSaveContext.cutsceneIndex == 0) {
gSaveContext.cutsceneIndex == 0
) {
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
*should = true; *should = true;
} }

View file

@ -48,7 +48,8 @@ void SkipChildRutoInteractions_Register() {
} }
}); });
// Prevents Ruto from running to the Sapphire when she wants to be tossed to it, instead she just stands up and waits for link to get closer // Prevents Ruto from running to the Sapphire when she wants to be tossed to it, instead she just stands up and
// waits for link to get closer
REGISTER_VB_SHOULD(VB_RUTO_RUN_TO_SAPPHIRE, { REGISTER_VB_SHOULD(VB_RUTO_RUN_TO_SAPPHIRE, {
EnRu1* enRu1 = va_arg(args, EnRu1*); EnRu1* enRu1 = va_arg(args, EnRu1*);
DynaPolyActor* dynaPolyActor = va_arg(args, DynaPolyActor*); DynaPolyActor* dynaPolyActor = va_arg(args, DynaPolyActor*);
@ -68,7 +69,8 @@ void SkipChildRutoInteractions_Register() {
// If we aren't skipping one point cutscenes and BgBdan objects has set the camera setting // If we aren't skipping one point cutscenes and BgBdan objects has set the camera setting
// to CAM_SET_NORMAL1 (2), don't reset the camera setting to 1. This prevents the One Point // to CAM_SET_NORMAL1 (2), don't reset the camera setting to 1. This prevents the One Point
// Cutscene of Ruto getting lifted up from getting queued up twice. // Cutscene of Ruto getting lifted up from getting queued up twice.
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) || enRu1->unk_28C->cameraSetting != 2) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) ||
enRu1->unk_28C->cameraSetting != 2) {
enRu1->unk_28C->cameraSetting = 1; enRu1->unk_28C->cameraSetting = 1;
} }
Actor* sapphire = func_80AEB124(gPlayState); Actor* sapphire = func_80AEB124(gPlayState);
@ -80,7 +82,8 @@ void SkipChildRutoInteractions_Register() {
} }
}); });
// This overrides the behavior that causes Ruto to get upset at you before sitting back down again when INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME is set // This overrides the behavior that causes Ruto to get upset at you before sitting back down again when
// INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME is set
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_RU1, [](void* actorRef) { GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_RU1, [](void* actorRef) {
EnRu1* enRu1 = static_cast<EnRu1*>(actorRef); EnRu1* enRu1 = static_cast<EnRu1*>(actorRef);
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {

View file

@ -11,7 +11,11 @@
#include <filesystem> #include <filesystem>
#define SEQUENCE_MAP_ENTRY(sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement) \ #define SEQUENCE_MAP_ENTRY(sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement) \
{ sequenceId, { sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement } } { \
sequenceId, { \
sequenceId, label, sfxKey, category, canBeReplaced, canBeUsedAsReplacement \
} \
}
AudioCollection::AudioCollection() { AudioCollection::AudioCollection() {
// clang-format off // clang-format off
@ -357,8 +361,11 @@ void AudioCollection::AddToCollection(char* otrPath, uint16_t seqNum) {
} }
SequenceInfo info = { seqNum, SequenceInfo info = { seqNum,
sequenceName, sequenceName,
StringHelper::Replace(StringHelper::Replace(StringHelper::Replace(sequenceName, " ", "_"), "~", "-"),".", ""), StringHelper::Replace(
type, false, true}; StringHelper::Replace(StringHelper::Replace(sequenceName, " ", "_"), "~", "-"), ".", ""),
type,
false,
true };
sequenceMap.emplace(seqNum, info); sequenceMap.emplace(seqNum, info);
} }
@ -367,7 +374,8 @@ uint16_t AudioCollection::GetReplacementSequence(uint16_t seqId) {
// for Hyrule Field instead. Otherwise, leave it alone, so that without any sfx editor modifications we will // for Hyrule Field instead. Otherwise, leave it alone, so that without any sfx editor modifications we will
// play the normal track as usual. // play the normal track as usual.
if (seqId == NA_BGM_FIELD_MORNING) { if (seqId == NA_BGM_FIELD_MORNING) {
if (CVarGetInteger(CVAR_AUDIO("ReplacedSequences.NA_BGM_FIELD_LOGIC.value"), NA_BGM_FIELD_LOGIC) != NA_BGM_FIELD_LOGIC) { if (CVarGetInteger(CVAR_AUDIO("ReplacedSequences.NA_BGM_FIELD_LOGIC.value"), NA_BGM_FIELD_LOGIC) !=
NA_BGM_FIELD_LOGIC) {
seqId = NA_BGM_FIELD_LOGIC; seqId = NA_BGM_FIELD_LOGIC;
} }
} }
@ -402,10 +410,12 @@ void AudioCollection::AddToShufflePool(SequenceInfo* seqInfo) {
} }
void AudioCollection::InitializeShufflePool() { void AudioCollection::InitializeShufflePool() {
if (shufflePoolInitialized) return; if (shufflePoolInitialized)
return;
for (auto& [seqId, seqInfo] : sequenceMap) { for (auto& [seqId, seqInfo] : sequenceMap) {
if (!seqInfo.canBeUsedAsReplacement) continue; if (!seqInfo.canBeUsedAsReplacement)
continue;
const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo.sfxKey; const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo.sfxKey;
if (CVarGetInteger(cvarKey.c_str(), 0)) { if (CVarGetInteger(cvarKey.c_str(), 0)) {
excludedSequences.insert(&seqInfo); excludedSequences.insert(&seqInfo);

View file

@ -101,7 +101,8 @@ void RandomizeGroup(SeqType type) {
} }
// if we didn't find any, return early without shuffling to prevent an infinite loop // if we didn't find any, return early without shuffling to prevent an infinite loop
if (!values.size()) return; if (!values.size())
return;
} }
Shuffle(values); Shuffle(values);
for (const auto& [seqId, seqData] : AudioCollection::Instance->GetAllSequences()) { for (const auto& [seqId, seqData] : AudioCollection::Instance->GetAllSequences()) {
@ -110,7 +111,9 @@ void RandomizeGroup(SeqType type) {
// don't randomize locked entries // don't randomize locked entries
if ((seqData.category & type) && CVarGetInteger(cvarLockKey.c_str(), 0) == 0) { if ((seqData.category & type) && CVarGetInteger(cvarLockKey.c_str(), 0) == 0) {
// Only save authentic sequence CVars // Only save authentic sequence CVars
if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) && seqData.sequenceId >= MAX_AUTHENTIC_SEQID) || seqData.canBeReplaced == false) { if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) &&
seqData.sequenceId >= MAX_AUTHENTIC_SEQID) ||
seqData.canBeReplaced == false) {
continue; continue;
} }
const int randomValue = values.back(); const int randomValue = values.back();
@ -273,7 +276,9 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
continue; continue;
} }
// Do not display custom sequences in the list // Do not display custom sequences in the list
if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) && defaultValue >= MAX_AUTHENTIC_SEQID) || seqData.canBeReplaced == false) { if ((((seqData.category & SEQ_BGM_CUSTOM) || seqData.category == SEQ_FANFARE) &&
defaultValue >= MAX_AUTHENTIC_SEQID) ||
seqData.canBeReplaced == false) {
continue; continue;
} }
@ -296,8 +301,10 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
UIWidgets::PushStyleCombobox(THEME_COLOR); UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo(hiddenKey.c_str(), map.at(initialValue).label.c_str())) { if (ImGui::BeginCombo(hiddenKey.c_str(), map.at(initialValue).label.c_str())) {
for (const auto& [value, seqData] : map) { for (const auto& [value, seqData] : map) {
// If excluded as a replacement sequence, don't show in other dropdowns except the effect's own dropdown. // If excluded as a replacement sequence, don't show in other dropdowns except the effect's own
if (~(seqData.category) & type || (!seqData.canBeUsedAsReplacement && initialSfxKey != seqData.sfxKey)) { // dropdown.
if (~(seqData.category) & type ||
(!seqData.canBeUsedAsReplacement && initialSfxKey != seqData.sfxKey)) {
continue; continue;
} }
@ -317,7 +324,9 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
UIWidgets::PopStyleCombobox(); UIWidgets::PopStyleCombobox();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
DrawPreviewButton((type == SEQ_SFX || type == SEQ_VOICE || type == SEQ_INSTRUMENT) ? defaultValue : currentValue, seqData.sfxKey, type); DrawPreviewButton((type == SEQ_SFX || type == SEQ_VOICE || type == SEQ_INSTRUMENT) ? defaultValue
: currentValue,
seqData.sfxKey, type);
auto locked = CVarGetInteger(cvarLockKey.c_str(), 0) == 1; auto locked = CVarGetInteger(cvarLockKey.c_str(), 0) == 1;
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
@ -442,7 +451,6 @@ void DrawTypeChip(SeqType type, std::string sequenceName) {
ImGui::EndDisabled(); ImGui::EndDisabled();
} }
void AudioEditorRegisterOnSceneInitHook() { void AudioEditorRegisterOnSceneInitHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
if (gSaveContext.gameMode != GAMEMODE_END_CREDITS && CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0)) { if (gSaveContext.gameMode != GAMEMODE_END_CREDITS && CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0)) {
@ -482,8 +490,7 @@ void AudioEditor::DrawElement() {
AudioEditor_LockAll(); AudioEditor_LockAll();
} }
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Unlock All Groups", if (UIWidgets::Button("Unlock All Groups", UIWidgets::ButtonOptions()
UIWidgets::ButtonOptions()
.Size(ImVec2(230.0f, 0.0f)) .Size(ImVec2(230.0f, 0.0f))
.Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Unlocks all music and sound effects across tab groups"))) { .Tooltip("Unlocks all music and sound effects across tab groups"))) {
@ -610,15 +617,9 @@ void AudioEditor::DrawElement() {
} }
static std::map<SeqType, bool> showType{ static std::map<SeqType, bool> showType{
{SEQ_BGM_WORLD, true}, { SEQ_BGM_WORLD, true }, { SEQ_BGM_EVENT, true }, { SEQ_BGM_BATTLE, true },
{SEQ_BGM_EVENT, true}, { SEQ_OCARINA, true }, { SEQ_FANFARE, true }, { SEQ_SFX, true },
{SEQ_BGM_BATTLE, true}, { SEQ_VOICE, true }, { SEQ_INSTRUMENT, true }, { SEQ_BGM_CUSTOM, true },
{SEQ_OCARINA, true},
{SEQ_FANFARE, true},
{SEQ_SFX, true },
{SEQ_VOICE, true },
{SEQ_INSTRUMENT, true},
{SEQ_BGM_CUSTOM, true},
}; };
// make temporary sets because removing from the set we're iterating through crashes ImGui // make temporary sets because removing from the set we're iterating through crashes ImGui
@ -648,7 +649,8 @@ void AudioEditor::DrawElement() {
} }
} }
ImGui::BeginTable("sequenceTypes", 9, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders); ImGui::BeginTable("sequenceTypes", 9,
ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::PushStyleColor(ImGuiCol_Header, GetSequenceTypeColor(SEQ_BGM_WORLD)); ImGui::PushStyleColor(ImGuiCol_Header, GetSequenceTypeColor(SEQ_BGM_WORLD));
@ -772,7 +774,9 @@ void AudioEditor::DrawElement() {
UIWidgets::PopStyleTabs(); UIWidgets::PopStyleTabs();
} }
std::vector<SeqType> allTypes = { SEQ_BGM_WORLD, SEQ_BGM_EVENT, SEQ_BGM_BATTLE, SEQ_OCARINA, SEQ_FANFARE, SEQ_INSTRUMENT, SEQ_SFX, SEQ_VOICE, }; std::vector<SeqType> allTypes = {
SEQ_BGM_WORLD, SEQ_BGM_EVENT, SEQ_BGM_BATTLE, SEQ_OCARINA, SEQ_FANFARE, SEQ_INSTRUMENT, SEQ_SFX, SEQ_VOICE,
};
void AudioEditor_RandomizeAll() { void AudioEditor_RandomizeAll() {
for (auto type : allTypes) { for (auto type : allTypes) {

View file

@ -29,7 +29,6 @@ extern "C" {
u16 AudioEditor_GetReplacementSeq(u16 seqId); u16 AudioEditor_GetReplacementSeq(u16 seqId);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -12,8 +12,7 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h" #include "soh/cvar_prefixes.h"
void BootCommands_Init() void BootCommands_Init() {
{
// Clears vars to prevent randomizer menu from being disabled // Clears vars to prevent randomizer menu from being disabled
CVarClear(CVAR_GENERAL("RandoGenerating")); // Clear when a crash happened during rando seed generation CVarClear(CVAR_GENERAL("RandoGenerating")); // Clear when a crash happened during rando seed generation
CVarClear(CVAR_GENERAL("NewSeedGenerated")); CVarClear(CVAR_GENERAL("NewSeedGenerated"));

View file

@ -28,17 +28,14 @@ typedef struct BossRushSetting {
} BossRushSetting; } BossRushSetting;
BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = { BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = {
{ { { "BOSSES:", "BOSSE:", "BOSS:" },
{ "BOSSES:", "BOSSE:", "BOSS:" },
{ {
{ "All", "Alle", "Tous" }, { "All", "Alle", "Tous" },
{ "Child", "Kind", "Enfant" }, { "Child", "Kind", "Enfant" },
{ "Adult", "Erwachsener", "Adulte" }, { "Adult", "Erwachsener", "Adulte" },
{ "Ganondorf & Ganon", "Ganondorf & Ganon", "Ganondorf & Ganon" }, { "Ganondorf & Ganon", "Ganondorf & Ganon", "Ganondorf & Ganon" },
} } },
}, { { "HEARTS:", "HERZEN:", "COEURS:" },
{
{ "HEARTS:", "HERZEN:", "COEURS:" },
{ {
{ "10", "10", "10" }, { "10", "10", "10" },
{ "15", "15", "15" }, { "15", "15", "15" },
@ -46,47 +43,35 @@ BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = {
{ "3", "3", "3" }, { "3", "3", "3" },
{ "5", "5", "5" }, { "5", "5", "5" },
{ "7", "7", "7" }, { "7", "7", "7" },
} } },
}, { { "AMMO:", "MUNITION:", "MUNITIONS:" },
{
{ "AMMO:", "MUNITION:", "MUNITIONS:" },
{ {
{ "Limited", "Limitiert", "Limitées" }, { "Limited", "Limitiert", "Limitées" },
{ "Full", "Voll", "Pleines" }, { "Full", "Voll", "Pleines" },
{ "Maxed", "Maximum", "Maximum" }, { "Maxed", "Maximum", "Maximum" },
} } },
}, { { "HEAL:", "REGENERATION:", "SOIN:" },
{
{ "HEAL:", "REGENERATION:", "SOIN:" },
{ {
{ "Before Ganondorf", "Vor Ganondorf", "Avant Ganondorf" }, { "Before Ganondorf", "Vor Ganondorf", "Avant Ganondorf" },
{ "Every Boss", "Bei jedem Boss", "Tous les Boss" }, { "Every Boss", "Bei jedem Boss", "Tous les Boss" },
{ "Never", "Niemals", "Jamais" }, { "Never", "Niemals", "Jamais" },
} } },
}, { { "HYPER BOSSES:", "HYPER-BOSSE:", "HYPER BOSS:" },
{
{ "HYPER BOSSES:", "HYPER-BOSSE:", "HYPER BOSS:" },
{ {
{ "No", "Nein", "Non" }, { "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" }, { "Yes", "Ja", "Oui" },
} } },
}, { { "MAGIC:", "MAGIE:", "MAGIE:" },
{
{ "MAGIC:", "MAGIE:", "MAGIE:" },
{ {
{ "Single", "Einzel", "Simple" }, { "Single", "Einzel", "Simple" },
{ "Double", "Doppel", "Double" }, { "Double", "Doppel", "Double" },
} } },
}, { { "BIG. SWORD:", "BIG.-SCHWERT:", "EPÉE DE BIG.:" },
{
{ "BIG. SWORD:", "BIG.-SCHWERT:", "EPÉE DE BIG.:" },
{ {
{ "No", "Nein", "Non" }, { "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" }, { "Yes", "Ja", "Oui" },
} } },
}, { { "BOTTLE:", "FLASCHEN:", "BOUTEILLE:" },
{
{ "BOTTLE:", "FLASCHEN:", "BOUTEILLE:" },
{ {
{ "No", "Nein", "Non" }, { "No", "Nein", "Non" },
{ "Empty", "Leer", "Vide" }, { "Empty", "Leer", "Vide" },
@ -94,36 +79,27 @@ BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = {
{ "Red Potion", "Rotes Elixier", "Potion Rouge" }, { "Red Potion", "Rotes Elixier", "Potion Rouge" },
{ "Green Potion", "Grünes Elixier", "Potion Verte" }, { "Green Potion", "Grünes Elixier", "Potion Verte" },
{ "Blue Potion", "Blaues Elixier", "Potion Bleue" }, { "Blue Potion", "Blaues Elixier", "Potion Bleue" },
} } },
}, { { "LONGSHOT:", "ENTERHAKEN:", "SUPER GRAPPIN:" },
{
{ "LONGSHOT:", "ENTERHAKEN:", "SUPER GRAPPIN:" },
{ {
{ "No", "Nein", "Non" }, { "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" }, { "Yes", "Ja", "Oui" },
} } },
}, { { "HOVER BOOTS:", "GLEITSTIEFEL:", "BOTTES DES AIRS:" },
{
{ "HOVER BOOTS:", "GLEITSTIEFEL:", "BOTTES DES AIRS:" },
{ {
{ "No", "Nein", "Non" }, { "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" }, { "Yes", "Ja", "Oui" },
} } },
}, { { "BUNNY HOOD:", "HASENOHREN:", "MASQUE DU LAPIN:" },
{
{ "BUNNY HOOD:", "HASENOHREN:", "MASQUE DU LAPIN:" },
{ {
{ "No", "Nein", "Non" }, { "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" }, { "Yes", "Ja", "Oui" },
} } },
}, { { "TIMER:", "TIMER:", "TIMER:" },
{
{ "TIMER:", "TIMER:", "TIMER:" },
{ {
{ "Yes", "Ja", "Oui" }, { "Yes", "Ja", "Oui" },
{ "No", "Nein", "Non" }, { "No", "Nein", "Non" },
} } }
}
}; };
const char* BossRush_GetSettingName(u8 optionIndex, u8 language) { const char* BossRush_GetSettingName(u8 optionIndex, u8 language) {
@ -253,7 +229,9 @@ void BossRush_HandleBlueWarp(PlayState* play, f32 warpPosX, f32 warpPosZ) {
} else if (warpPosX == -199 && warpPosZ == 0) { } else if (warpPosX == -199 && warpPosZ == 0) {
play->nextEntranceIndex = ENTR_GANONDORF_BOSS_0; play->nextEntranceIndex = ENTR_GANONDORF_BOSS_0;
} else { } else {
SPDLOG_ERROR("[BossRush]: Unknown blue warp in chamber of sages at position ({}, {}). Warping back to chamber of sages.", warpPosX, warpPosZ); SPDLOG_ERROR("[BossRush]: Unknown blue warp in chamber of sages at position ({}, {}). Warping back to "
"chamber of sages.",
warpPosX, warpPosZ);
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
} }
// If coming from a boss room, teleport back to Chamber of Sages and set flag. // If coming from a boss room, teleport back to Chamber of Sages and set flag.
@ -328,7 +306,8 @@ void BossRush_HandleCompleteBoss(PlayState* play) {
Health_ChangeBy(play, 320); Health_ChangeBy(play, 320);
} }
if ((CheckDungeonCount() == 3 && gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) || if ((CheckDungeonCount() == 3 &&
gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) ||
play->sceneNum == SCENE_GANON_BOSS) { play->sceneNum == SCENE_GANON_BOSS) {
gSaveContext.ship.stats.playTimer += 2; gSaveContext.ship.stats.playTimer += 2;
gSaveContext.ship.stats.gameComplete = 1; gSaveContext.ship.stats.gameComplete = 1;
@ -399,17 +378,17 @@ void BossRush_InitSave() {
gSaveContext.eventChkInf[7] |= 0x80; // bongo bongo gSaveContext.eventChkInf[7] |= 0x80; // bongo bongo
// Sets all rando flags to false // Sets all rando flags to false
// Boss Rush currently uses 2 randomizer flags (RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE & RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE) // Boss Rush currently uses 2 randomizer flags (RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE &
// RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)
for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.ship.randomizerInf); i++) { for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.ship.randomizerInf); i++) {
gSaveContext.ship.randomizerInf[i] = 0; gSaveContext.ship.randomizerInf[i] = 0;
} }
// Set items // Set items
std::array<u8, 24> brItems = { std::array<u8, 24> brItems = {
ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE,
ITEM_SLINGSHOT, ITEM_NONE, ITEM_NONE, ITEM_HOOKSHOT, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_HOOKSHOT, ITEM_NONE, ITEM_NONE, ITEM_BOOMERANG, ITEM_LENS, ITEM_NONE, ITEM_HAMMER,
ITEM_BOOMERANG, ITEM_LENS, ITEM_NONE, ITEM_HAMMER, ITEM_ARROW_LIGHT, ITEM_NONE, ITEM_ARROW_LIGHT, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
}; };
if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_LONGSHOT] == BR_CHOICE_LONGSHOT_YES) { if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_LONGSHOT] == BR_CHOICE_LONGSHOT_YES) {
@ -541,11 +520,13 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
break; break;
} }
} }
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, childPos.x, bossGoma->actor.world.pos.y, childPos.z, 0, 0, 0, WARP_DUNGEON_ADULT, false); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, childPos.x,
bossGoma->actor.world.pos.y, childPos.z, 0, 0, 0, WARP_DUNGEON_ADULT, false);
break; break;
} }
case SCENE_DODONGOS_CAVERN_BOSS: { case SCENE_DODONGOS_CAVERN_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, WARP_DUNGEON_ADULT, false); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0,
0, WARP_DUNGEON_ADULT, false);
break; break;
} }
case SCENE_JABU_JABU_BOSS: { case SCENE_JABU_JABU_BOSS: {
@ -563,28 +544,34 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
} }
} }
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, sWarpPos[sp7C].x, sWarpPos[sp7C].y, sWarpPos[sp7C].z, 0, 0, 0, WARP_DUNGEON_ADULT, false); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, sWarpPos[sp7C].x, sWarpPos[sp7C].y,
sWarpPos[sp7C].z, 0, 0, 0, WARP_DUNGEON_ADULT, false);
break; break;
} }
case SCENE_FOREST_TEMPLE_BOSS: { case SCENE_FOREST_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 14.0f, -33.0f, -3315.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 14.0f, -33.0f, -3315.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break; break;
} }
case SCENE_FIRE_TEMPLE_BOSS: { case SCENE_FIRE_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break; break;
} }
case SCENE_WATER_TEMPLE_BOSS: { case SCENE_WATER_TEMPLE_BOSS: {
BossMo* bossMo = va_arg(args, BossMo*); BossMo* bossMo = va_arg(args, BossMo*);
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, bossMo->actor.world.pos.x, -280.0f, bossMo->actor.world.pos.z, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, bossMo->actor.world.pos.x, -280.0f,
bossMo->actor.world.pos.z, 0, 0, 0, WARP_DUNGEON_ADULT, true);
break; break;
} }
case SCENE_SPIRIT_TEMPLE_BOSS: { case SCENE_SPIRIT_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break; break;
} }
case SCENE_SHADOW_TEMPLE_BOSS: { case SCENE_SHADOW_TEMPLE_BOSS: {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -50.0f, 0.0f, 400.0f, 0, 0, 0, WARP_DUNGEON_ADULT, true); Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_DOOR_WARP1, -50.0f, 0.0f, 400.0f, 0, 0, 0,
WARP_DUNGEON_ADULT, true);
break; break;
} }
default: { default: {
@ -699,12 +686,18 @@ void BossRush_RegisterHooks() {
onBossDefeatHook = 0; onBossDefeatHook = 0;
onActorUpdate = 0; onActorUpdate = 0;
if (!IS_BOSS_RUSH) return; if (!IS_BOSS_RUSH)
return;
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(BossRush_OnVanillaBehaviorHandler); onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(
onSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(BossRush_OnSceneInitHandler); BossRush_OnVanillaBehaviorHandler);
onActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(BossRush_OnActorInitHandler); onSceneInitHook =
onBossDefeatHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnBossDefeat>(BossRush_OnBossDefeatHandler); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(BossRush_OnSceneInitHandler);
onActorUpdate = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_DOOR_WARP1, BossRush_OnBlueWarpUpdate); onActorInitHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(BossRush_OnActorInitHandler);
onBossDefeatHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnBossDefeat>(BossRush_OnBossDefeatHandler);
onActorUpdate = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(
ACTOR_DOOR_WARP1, BossRush_OnBlueWarpUpdate);
}); });
} }

View file

@ -20,15 +20,22 @@ static Color_RGBA8 textColorDefault = { 255, 255, 255, 255 };
static Color_RGBA8 range1ColorDefault = { 255, 178, 0, 255 }; static Color_RGBA8 range1ColorDefault = { 255, 178, 0, 255 };
static Color_RGBA8 range2ColorDefault = { 0, 255, 0, 255 }; static Color_RGBA8 range2ColorDefault = { 0, 255, 0, 255 };
static std::unordered_map<int32_t, const char*> buttonOutlineOptions = static std::unordered_map<int32_t, const char*> buttonOutlineOptions = {
{{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Always Shown" }, { BUTTON_OUTLINE_NOT_PRESSED, "Shown Only While Not Pressed" }, { BUTTON_OUTLINE_ALWAYS_SHOWN, "Always Shown" },
{ BUTTON_OUTLINE_PRESSED, "Shown Only While Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "Always Hidden" }}; { BUTTON_OUTLINE_NOT_PRESSED, "Shown Only While Not Pressed" },
static std::unordered_map<int32_t, const char*> buttonOutlineOptionsVerbose = { BUTTON_OUTLINE_PRESSED, "Shown Only While Pressed" },
{{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Outline Always Shown" }, { BUTTON_OUTLINE_NOT_PRESSED, "Outline Shown Only While Not Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "Always Hidden" }
{ BUTTON_OUTLINE_PRESSED, "Outline Shown Only While Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "Outline Always Hidden" }}; };
static std::unordered_map<int32_t, const char*> buttonOutlineOptionsVerbose = {
{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Outline Always Shown" },
{ BUTTON_OUTLINE_NOT_PRESSED, "Outline Shown Only While Not Pressed" },
{ BUTTON_OUTLINE_PRESSED, "Outline Shown Only While Pressed" },
{ BUTTON_OUTLINE_ALWAYS_HIDDEN, "Outline Always Hidden" }
};
static std::unordered_map<int32_t, const char*> stickModeOptions = static std::unordered_map<int32_t, const char*> stickModeOptions = { { STICK_MODE_ALWAYS_SHOWN, "Always" },
{{ STICK_MODE_ALWAYS_SHOWN, "Always" }, { STICK_MODE_HIDDEN_IN_DEADZONE, "While In Use" }, { STICK_MODE_ALWAYS_HIDDEN, "Never" }}; { STICK_MODE_HIDDEN_IN_DEADZONE, "While In Use" },
{ STICK_MODE_ALWAYS_HIDDEN, "Never" } };
InputViewer::~InputViewer() { InputViewer::~InputViewer() {
SPDLOG_TRACE("destruct input viewer"); SPDLOG_TRACE("destruct input viewer");
@ -68,66 +75,78 @@ void InputViewer::DrawElement() {
if (!sButtonTexturesLoaded) { if (!sButtonTexturesLoaded) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage( Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Input-Viewer-Background", "textures/buttons/InputViewerBackground.png"); "Input-Viewer-Background", "textures/buttons/InputViewerBackground.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png"); "textures/buttons/ABtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png"); "textures/buttons/BBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn", "textures/buttons/LBtn.png");
"textures/buttons/StartBtn.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png"); "textures/buttons/RBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png"); "textures/buttons/ZBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick", "Start-Btn", "textures/buttons/StartBtn.png");
"textures/buttons/AnalogStick.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left", "textures/buttons/CLeft.png");
"textures/buttons/DPadLeft.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right", "textures/buttons/CRight.png");
"textures/buttons/DPadRight.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up",
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); "textures/buttons/CUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down",
"textures/buttons/DPadDown.png"); "textures/buttons/CDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1", "textures/buttons/Mod1.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2", "textures/buttons/Mod2.png"); "Analog-Stick", "textures/buttons/AnalogStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/RightStick.png"); "Dpad-Left", "textures/buttons/DPadLeft.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/ABtnOutline.png"); "Dpad-Right", "textures/buttons/DPadRight.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up",
"textures/buttons/BBtnOutline.png"); "textures/buttons/DPadUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/LBtnOutline.png"); "Dpad-Down", "textures/buttons/DPadDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1",
"textures/buttons/RBtnOutline.png"); "textures/buttons/Mod1.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2",
"textures/buttons/ZBtnOutline.png"); "textures/buttons/Mod2.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/StartBtnOutline.png"); "Right-Stick", "textures/buttons/RightStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/CLeftOutline.png"); "A-Btn Outline", "textures/buttons/ABtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/CRightOutline.png"); "B-Btn Outline", "textures/buttons/BBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/CUpOutline.png"); "L-Btn Outline", "textures/buttons/LBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/CDownOutline.png"); "R-Btn Outline", "textures/buttons/RBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/AnalogStickOutline.png"); "Z-Btn Outline", "textures/buttons/ZBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/DPadLeftOutline.png"); "Start-Btn Outline", "textures/buttons/StartBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/DPadRightOutline.png"); "C-Left Outline", "textures/buttons/CLeftOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/DPadUpOutline.png"); "C-Right Outline", "textures/buttons/CRightOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/DPadDownOutline.png"); "C-Up Outline", "textures/buttons/CUpOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1 Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/Mod1Outline.png"); "C-Down Outline", "textures/buttons/CDownOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2 Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/Mod2Outline.png"); "Analog-Stick Outline", "textures/buttons/AnalogStickOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline", Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"textures/buttons/RightStickOutline.png"); "Dpad-Left Outline", "textures/buttons/DPadLeftOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Right Outline", "textures/buttons/DPadRightOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Up Outline", "textures/buttons/DPadUpOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Down Outline", "textures/buttons/DPadDownOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Modifier-1 Outline", "textures/buttons/Mod1Outline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Modifier-2 Outline", "textures/buttons/Mod2Outline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Right-Stick Outline", "textures/buttons/RightStickOutline.png");
sButtonTexturesLoaded = true; sButtonTexturesLoaded = true;
} }
@ -140,7 +159,8 @@ void InputViewer::DrawElement() {
const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f); const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f);
#endif #endif
const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0); const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0);
const int buttonOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED); const int buttonOutlineMode =
CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED);
const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1);
ImVec2 bgSize = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background"); ImVec2 bgSize = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background");
@ -161,7 +181,8 @@ void InputViewer::DrawElement() {
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
OSContPad* pads = std::dynamic_pointer_cast<LUS::ControlDeck>(Ship::Context::GetInstance()->GetControlDeck())->GetPads(); OSContPad* pads =
std::dynamic_pointer_cast<LUS::ControlDeck>(Ship::Context::GetInstance()->GetControlDeck())->GetPads();
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground |
@ -266,9 +287,9 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize,
useGlobalOutlineMode useGlobalOutlineMode ? buttonOutlineMode
? buttonOutlineMode : CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"),
: CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); BUTTON_OUTLINE_NOT_PRESSED));
} }
// Dpad // Dpad
@ -371,7 +392,8 @@ void InputViewer::DrawElement() {
// Analog stick angle text // Analog stick angle text
if (showAnalogAngles) { if (showAnalogAngles) {
ImGui::SetCursorPos(ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale, ImGui::SetCursorPos(
ImVec2(aPos.x + 10 + CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 0) * scale,
scaledBGSize.y + aPos.y + 10)); scaledBGSize.y + aPos.y + 10));
// Scale font with input viewer scale // Scale font with input viewer scale
float oldFontScale = ImGui::GetFont()->Scale; float oldFontScale = ImGui::GetFont()->Scale;
@ -392,17 +414,16 @@ void InputViewer::DrawElement() {
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) && if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) &&
(rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) { (rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) {
ImGui::PushStyleColor( ImGui::PushStyleColor(
ImGuiCol_Text, ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"),
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"), range1ColorDefault))); range1ColorDefault)));
} } else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) &&
else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) &&
(rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) { (rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) {
ImGui::PushStyleColor( ImGui::PushStyleColor(
ImGuiCol_Text, ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"),
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"), range2ColorDefault))); range2ColorDefault)));
} } else {
else { ImGui::PushStyleColor(ImGuiCol_Text,
ImGui::PushStyleColor(ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"), VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"),
textColorDefault))); textColorDefault)));
} }
@ -430,15 +451,23 @@ InputViewerSettingsWindow::~InputViewerSettingsWindow() {
void InputViewerSettingsWindow::DrawElement() { void InputViewerSettingsWindow::DrawElement() {
// gInputViewer.Scale // gInputViewer.Scale
CVarSliderFloat("Input Viewer Scale: %.2f", CVAR_INPUT_VIEWER("Scale"), CVarSliderFloat("Input Viewer Scale: %.2f", CVAR_INPUT_VIEWER("Scale"),
FloatSliderOptions().Color(THEME_COLOR).DefaultValue(1.0f).Min(0.1f).Max(5.0f).ShowButtons(true).Tooltip("Sets the on screen size of the input viewer")); FloatSliderOptions()
.Color(THEME_COLOR)
.DefaultValue(1.0f)
.Min(0.1f)
.Max(5.0f)
.ShowButtons(true)
.Tooltip("Sets the on screen size of the input viewer"));
// gInputViewer.EnableDragging // gInputViewer.EnableDragging
CVarCheckbox("Enable Dragging", CVAR_INPUT_VIEWER("EnableDragging"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Enable Dragging", CVAR_INPUT_VIEWER("EnableDragging"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
// gInputViewer.ShowBackground // gInputViewer.ShowBackground
CVarCheckbox("Show Background Layer", CVAR_INPUT_VIEWER("ShowBackground"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show Background Layer", CVAR_INPUT_VIEWER("ShowBackground"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
@ -446,21 +475,26 @@ void InputViewerSettingsWindow::DrawElement() {
if (ImGui::CollapsingHeader("Buttons")) { if (ImGui::CollapsingHeader("Buttons")) {
// gInputViewer.ButtonOutlineMode // gInputViewer.ButtonOutlineMode
CVarCombobox("Button Outlines/Backgrounds", CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions, CVarCombobox(
ComboboxOptions({{ .disabled = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1), .disabledTooltip = "Disabled because Global Button Outline is off" }}) "Button Outlines/Backgrounds", CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions,
.Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED) ComboboxOptions({ { .disabled = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1),
.disabledTooltip = "Disabled because Global Button Outline is off" } })
.Color(THEME_COLOR)
.DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)
.Tooltip("Sets the desired visibility behavior for the button outline/background layers. Useful for " .Tooltip("Sets the desired visibility behavior for the button outline/background layers. Useful for "
"custom input viewers.")); "custom input viewers."));
// gInputViewer.UseGlobalButtonOutlineMode // gInputViewer.UseGlobalButtonOutlineMode
CVarCheckbox("Use for all buttons", CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Use for all buttons", CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
UIWidgets::PaddedSeparator(); UIWidgets::PaddedSeparator();
bool useIndividualOutlines = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); bool useIndividualOutlines = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1);
// gInputViewer.ABtn // gInputViewer.ABtn
CVarCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##ABtnOutline", CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##ABtnOutline", CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -468,7 +502,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.BBtn // gInputViewer.BBtn
CVarCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##BBtnOutline", CVAR_INPUT_VIEWER("BBtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##BBtnOutline", CVAR_INPUT_VIEWER("BBtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -476,7 +511,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.CUp // gInputViewer.CUp
CVarCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##CUpOutline", CVAR_INPUT_VIEWER("CUpOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##CUpOutline", CVAR_INPUT_VIEWER("CUpOutlineMode"), buttonOutlineOptionsVerbose,
@ -484,7 +520,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.CRight // gInputViewer.CRight
CVarCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##CRightOutline", CVAR_INPUT_VIEWER("CRightOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##CRightOutline", CVAR_INPUT_VIEWER("CRightOutlineMode"), buttonOutlineOptionsVerbose,
@ -492,7 +529,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.CDown // gInputViewer.CDown
CVarCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##CDownOutline", CVAR_INPUT_VIEWER("CDownOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##CDownOutline", CVAR_INPUT_VIEWER("CDownOutlineMode"), buttonOutlineOptionsVerbose,
@ -500,7 +538,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.CLeft // gInputViewer.CLeft
CVarCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##CLeftOutline", CVAR_INPUT_VIEWER("CLeftOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##CLeftOutline", CVAR_INPUT_VIEWER("CLeftOutlineMode"), buttonOutlineOptionsVerbose,
@ -508,7 +547,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.LBtn // gInputViewer.LBtn
CVarCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##LBtnOutline", CVAR_INPUT_VIEWER("LBtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##LBtnOutline", CVAR_INPUT_VIEWER("LBtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -516,7 +556,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.RBtn // gInputViewer.RBtn
CVarCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##RBtnOutline", CVAR_INPUT_VIEWER("RBtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##RBtnOutline", CVAR_INPUT_VIEWER("RBtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -524,7 +565,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.ZBtn // gInputViewer.ZBtn
CVarCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##ZBtnOutline", CVAR_INPUT_VIEWER("ZBtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##ZBtnOutline", CVAR_INPUT_VIEWER("ZBtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -532,7 +574,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.StartBtn // gInputViewer.StartBtn
CVarCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##StartBtnOutline", CVAR_INPUT_VIEWER("StartBtnOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##StartBtnOutline", CVAR_INPUT_VIEWER("StartBtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -540,7 +583,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.Dpad // gInputViewer.Dpad
CVarCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##DpadOutline", CVAR_INPUT_VIEWER("DpadOutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##DpadOutline", CVAR_INPUT_VIEWER("DpadOutlineMode"), buttonOutlineOptionsVerbose,
@ -548,7 +592,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.Mod1 // gInputViewer.Mod1
CVarCheckbox("Show Modifier Button 1 Layers", CVAR_INPUT_VIEWER("Mod1"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show Modifier Button 1 Layers", CVAR_INPUT_VIEWER("Mod1"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##Mmod1Outline", CVAR_INPUT_VIEWER("Mod1OutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##Mmod1Outline", CVAR_INPUT_VIEWER("Mod1OutlineMode"), buttonOutlineOptionsVerbose,
@ -556,7 +601,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent(); ImGui::Unindent();
} }
// gInputViewer.Mod2 // gInputViewer.Mod2
CVarCheckbox("Show Modifier Button 2 Layers", CVAR_INPUT_VIEWER("Mod2"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true)); CVarCheckbox("Show Modifier Button 2 Layers", CVAR_INPUT_VIEWER("Mod2"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true));
if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) {
ImGui::Indent(); ImGui::Indent();
CVarCombobox("##Mod2Outline", CVAR_INPUT_VIEWER("Mod2OutlineMode"), buttonOutlineOptionsVerbose, CVarCombobox("##Mod2Outline", CVAR_INPUT_VIEWER("Mod2OutlineMode"), buttonOutlineOptionsVerbose,
@ -569,72 +615,124 @@ void InputViewerSettingsWindow::DrawElement() {
if (ImGui::CollapsingHeader("Analog Stick")) { if (ImGui::CollapsingHeader("Analog Stick")) {
// gInputViewer.AnalogStick.VisibilityMode // gInputViewer.AnalogStick.VisibilityMode
CVarCombobox("Analog Stick Visibility", CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions, CVarCombobox(
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN) "Analog Stick Visibility", CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions,
.Tooltip("Determines the conditions under which the moving layer of the analog stick texture is visible.")); ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the moving layer of the analog stick texture is visible."));
// gInputViewer.AnalogStick.OutlineMode // gInputViewer.AnalogStick.OutlineMode
CVarCombobox("Analog Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), stickModeOptions, CVarCombobox(
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN) "Analog Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"),
.Tooltip("Determines the conditions under which the analog stick outline/background texture is visible.")); stickModeOptions,
ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the analog stick outline/background texture is visible."));
// gInputViewer.AnalogStick.Movement // gInputViewer.AnalogStick.Movement
CVarSliderInt("Analog Stick Movement: %dpx", CVAR_INPUT_VIEWER("AnalogStick.Movement"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(200).DefaultValue(12).ShowButtons(true) CVarSliderInt("Analog Stick Movement: %dpx", CVAR_INPUT_VIEWER("AnalogStick.Movement"),
.Tooltip("Sets the distance to move the analog stick in the input viewer. Useful for custom input viewers.")); IntSliderOptions()
.Color(THEME_COLOR)
.Min(0)
.Max(200)
.DefaultValue(12)
.ShowButtons(true)
.Tooltip("Sets the distance to move the analog stick in the input viewer. Useful for custom "
"input viewers."));
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
} }
if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) { if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) {
// gInputViewer.RightStick.VisibilityMode // gInputViewer.RightStick.VisibilityMode
CVarCombobox("Right Stick Visibility", CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions, CVarCombobox(
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN) "Right Stick Visibility", CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions,
.Tooltip("Determines the conditions under which the moving layer of the right stick texture is visible.")); ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the moving layer of the right stick texture is visible."));
// gInputViewer.RightStick.OutlineMode // gInputViewer.RightStick.OutlineMode
CVarCombobox("Right Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions, CVarCombobox(
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN) "Right Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions,
.Tooltip("Determines the conditions under which the right stick outline/background texture is visible.")); ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip(
"Determines the conditions under which the right stick outline/background texture is visible."));
// gInputViewer.RightStick.Movement // gInputViewer.RightStick.Movement
CVarSliderInt("Right Stick Movement: %dpx", CVAR_INPUT_VIEWER("RightStick.Movement"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(200).DefaultValue(7).ShowButtons(true) CVarSliderInt(
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for custom input viewers.")); "Right Stick Movement: %dpx", CVAR_INPUT_VIEWER("RightStick.Movement"),
IntSliderOptions()
.Color(THEME_COLOR)
.Min(0)
.Max(200)
.DefaultValue(7)
.ShowButtons(true)
.Tooltip(
"Sets the distance to move the right stick in the input viewer. Useful for custom input viewers."));
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
} }
if (ImGui::CollapsingHeader("Analog Angle Values")) { if (ImGui::CollapsingHeader("Analog Angle Values")) {
// gAnalogAngles // gAnalogAngles
CVarCheckbox("Show Analog Stick Angle Values", CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox(
.Tooltip("Displays analog stick angle values in the input viewer")); "Show Analog Stick Angle Values", CVAR_INPUT_VIEWER("AnalogAngles.Enabled"),
CheckboxOptions().Color(THEME_COLOR).Tooltip("Displays analog stick angle values in the input viewer"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0)) {
// gInputViewer.AnalogAngles.TextColor // gInputViewer.AnalogAngles.TextColor
CVarColorPicker("Text Color", CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), textColorDefault, CVarColorPicker("Text Color", CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), textColorDefault, true,
true, ColorPickerRandomButton | ColorPickerResetButton); ColorPickerRandomButton | ColorPickerResetButton);
// gAnalogAngleScale // gAnalogAngleScale
CVarSliderFloat("Angle Text Scale: %.2f%%", CVAR_INPUT_VIEWER("AnalogAngles.Scale"), CVarSliderFloat("Angle Text Scale: %.2f%%", CVAR_INPUT_VIEWER("AnalogAngles.Scale"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.1f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.1f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
// gInputViewer.AnalogAngles.Offset // gInputViewer.AnalogAngles.Offset
CVarSliderInt("Angle Text Offset: %dpx", CVAR_INPUT_VIEWER("AnalogAngles.Offset"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(400).DefaultValue(0).ShowButtons(true) CVarSliderInt("Angle Text Offset: %dpx", CVAR_INPUT_VIEWER("AnalogAngles.Offset"),
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for custom input viewers.")); IntSliderOptions()
.Color(THEME_COLOR)
.Min(0)
.Max(400)
.DefaultValue(0)
.ShowButtons(true)
.Tooltip("Sets the distance to move the right stick in the input viewer. Useful for "
"custom input viewers."));
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
// gInputViewer.AnalogAngles.Range1.Enabled // gInputViewer.AnalogAngles.Range1.Enabled
CVarCheckbox("Highlight ESS Position", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox(
.Tooltip("Highlights the angle value text when the analog stick is in ESS position (on flat ground)")); "Highlight ESS Position", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip(
"Highlights the angle value text when the analog stick is in ESS position (on flat ground)"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0)) {
// gInputViewer.AnalogAngles.Range1.Color // gInputViewer.AnalogAngles.Range1.Color
CVarColorPicker("ESS Color", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), range1ColorDefault, CVarColorPicker("ESS Color", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), range1ColorDefault, true,
true, ColorPickerRandomButton | ColorPickerResetButton); ColorPickerRandomButton | ColorPickerResetButton);
} }
UIWidgets::PaddedSeparator(true, true); UIWidgets::PaddedSeparator(true, true);
// gInputViewer.AnalogAngles.Range2.Enabled // gInputViewer.AnalogAngles.Range2.Enabled
CVarCheckbox("Highlight Walking Speed Angles", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Highlight Walking Speed Angles", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Highlights the angle value text when the analog stick is at an angle that would " .Tooltip("Highlights the angle value text when the analog stick is at an angle that would "
"produce a walking speed (on flat ground)\n\n" "produce a walking speed (on flat ground)\n\n"
"Useful for 1.0 Empty Jumpslash Quick Put Away")); "Useful for 1.0 Empty Jumpslash Quick Put Away"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0)) { if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0)) {
// gInputViewer.AnalogAngles.Range2.Color // gInputViewer.AnalogAngles.Range2.Color
CVarColorPicker("Walking Speed Color", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"), range2ColorDefault, CVarColorPicker("Walking Speed Color", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"),
true, ColorPickerRandomButton | ColorPickerResetButton); range2ColorDefault, true, ColorPickerRandomButton | ColorPickerResetButton);
} }
} }
} }

View file

@ -42,10 +42,12 @@ void Mouse_HandleThirdPerson(f32* newCamX, f32* newCamY) {
void Mouse_HandleFirstPerson(Player* player) { void Mouse_HandleFirstPerson(Player* player) {
f32 xAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.X"), 1.0f); f32 xAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.X"), 1.0f);
f32 yAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.Y"), 1.0f); f32 yAxisMulti = CVarGetFloat(CVAR_SETTING("FirstPersonCameraSensitivity.Y"), 1.0f);
s8 invertXAxisMulti = ((CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) s8 invertXAxisMulti = ((CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) &&
&& !CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) !CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) ||
|| (!CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) (!CVarGetInteger(CVAR_SETTING("Controls.InvertAimingXAxis"), 0) &&
&& CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0))) ? -1 : 1; CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)))
? -1
: 1;
s8 invertYAxisMulti = CVarGetInteger(CVAR_SETTING("Controls.InvertAimingYAxis"), 1) ? 1 : -1; s8 invertYAxisMulti = CVarGetInteger(CVAR_SETTING("Controls.InvertAimingYAxis"), 1) ? 1 : -1;
if (MOUSE_ENABLED) { if (MOUSE_ENABLED) {
player->actor.focus.rot.y -= mouseCoordRel.x * 6.0f * xAxisMulti * invertXAxisMulti; player->actor.focus.rot.y -= mouseCoordRel.x * 6.0f * xAxisMulti * invertXAxisMulti;
@ -67,7 +69,8 @@ void Mouse_HandleShield(f32* sp50, f32* sp54) {
s32 height = GetWindow()->GetHeight(); s32 height = GetWindow()->GetHeight();
f32 xBound = 7200 / ((f32)width / 2); f32 xBound = 7200 / ((f32)width / 2);
f32 yBound = 6000 / ((f32)height / 2); f32 yBound = 6000 / ((f32)height / 2);
*sp50 += (mouseCoord.x - (width / 2)) * xBound * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 1 : -1); *sp50 +=
(mouseCoord.x - (width / 2)) * xBound * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 1 : -1);
*sp54 += (mouseCoord.y - (height / 2)) * yBound; *sp54 += (mouseCoord.y - (height / 2)) * yBound;
*sp50 = CLAMP(*sp50, -7200, 7200); *sp50 = CLAMP(*sp50, -7200, 7200);
*sp54 = CLAMP(*sp54, -6000, 6000); *sp54 = CLAMP(*sp54, -6000, 6000);

View file

@ -26,13 +26,9 @@ void SohInputEditorWindow::InitElement() {
mButtonsBitmasks = { BTN_A, BTN_B, BTN_START, BTN_L, BTN_R, BTN_Z, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT }; mButtonsBitmasks = { BTN_A, BTN_B, BTN_START, BTN_L, BTN_R, BTN_Z, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT };
mDpadBitmasks = { BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT }; mDpadBitmasks = { BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT };
mModifierButtonsBitmasks = { BTN_CUSTOM_MODIFIER1, BTN_CUSTOM_MODIFIER2 }; mModifierButtonsBitmasks = { BTN_CUSTOM_MODIFIER1, BTN_CUSTOM_MODIFIER2 };
mCustomOcarinaButtonsBitmasks = { mCustomOcarinaButtonsBitmasks = { BTN_CUSTOM_OCARINA_NOTE_D4, BTN_CUSTOM_OCARINA_NOTE_F4,
BTN_CUSTOM_OCARINA_NOTE_D4, BTN_CUSTOM_OCARINA_NOTE_A4, BTN_CUSTOM_OCARINA_NOTE_B4,
BTN_CUSTOM_OCARINA_NOTE_F4, BTN_CUSTOM_OCARINA_NOTE_D5 };
BTN_CUSTOM_OCARINA_NOTE_A4,
BTN_CUSTOM_OCARINA_NOTE_B4,
BTN_CUSTOM_OCARINA_NOTE_D5
};
addButtonName(BTN_A, "A"); addButtonName(BTN_A, "A");
addButtonName(BTN_B, "B"); addButtonName(BTN_B, "B");
@ -669,8 +665,8 @@ void SohInputEditorWindow::DrawStickSection(uint8_t port, uint8_t stick, int32_t
} }
ImGui::SameLine(0.0f, 0.0f); ImGui::SameLine(0.0f, 0.0f);
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f)); ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
if (ImGui::SliderInt(StringHelper::Sprintf("##Sensitivity%d", id).c_str(), &sensitivityPercentage, 0, 200, "%d%%", if (ImGui::SliderInt(StringHelper::Sprintf("##Sensitivity%d", id).c_str(), &sensitivityPercentage, 0, 200,
ImGuiSliderFlags_AlwaysClamp)) { "%d%%", ImGuiSliderFlags_AlwaysClamp)) {
controllerStick->SetSensitivity(sensitivityPercentage); controllerStick->SetSensitivity(sensitivityPercentage);
} }
ImGui::SameLine(0.0f, 0.0f); ImGui::SameLine(0.0f, 0.0f);
@ -1070,7 +1066,11 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
"Original Tunic Colors", "Cosmetics Tunic Colors", "Health Colors", "Original Tunic Colors", "Cosmetics Tunic Colors", "Health Colors",
"Original Navi Targeting Colors", "Cosmetics Navi Targeting Colors", "Custom" "Original Navi Targeting Colors", "Cosmetics Navi Targeting Colors", "Custom"
}; };
CVarCombobox("Source", CVAR_SETTING("LEDColorSource"), ledSources, UIWidgets::ComboboxOptions().Color(THEME_COLOR).DefaultIndex(LED_SOURCE_TUNIC_ORIGINAL) CVarCombobox(
"Source", CVAR_SETTING("LEDColorSource"), ledSources,
UIWidgets::ComboboxOptions()
.Color(THEME_COLOR)
.DefaultIndex(LED_SOURCE_TUNIC_ORIGINAL)
.Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when " .Tooltip("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when "
"health < 40%. Green otherwise.\n\n" "health < 40%. Green otherwise.\n\n"
"Tunics: colors will mirror currently equipped tunic, whether original or the current " "Tunics: colors will mirror currently equipped tunic, whether original or the current "
@ -1094,12 +1094,21 @@ void SohInputEditorWindow::DrawLEDSection(uint8_t port) {
ImGui::Text("Custom Color"); ImGui::Text("Custom Color");
} }
CVarSliderFloat("Brightness: %.1f %%", CVAR_SETTING("LEDBrightness"), CVarSliderFloat("Brightness: %.1f %%", CVAR_SETTING("LEDBrightness"),
FloatSliderOptions().IsPercentage().Min(0.0f).Max(1.0f).DefaultValue(1.0f).ShowButtons(true) FloatSliderOptions()
.IsPercentage()
.Min(0.0f)
.Max(1.0f)
.DefaultValue(1.0f)
.ShowButtons(true)
.Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off.")); .Tooltip("Sets the brightness of controller LEDs. 0% brightness = LEDs off."));
CVarCheckbox("Critical Health Override", CVAR_SETTING("LEDCriticalOverride"), CVarCheckbox(
CheckboxOptions({{ .disabled = CVarGetInteger(CVAR_SETTING("LEDColorSource"), LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH, "Critical Health Override", CVAR_SETTING("LEDCriticalOverride"),
.disabledTooltip = "Override redundant for health source."}}).DefaultValue(true) CheckboxOptions({ { .disabled = CVarGetInteger(CVAR_SETTING("LEDColorSource"),
.Tooltip("Shows red color when health is critical, otherwise displays according to color source.")); LED_SOURCE_TUNIC_ORIGINAL) == LED_SOURCE_HEALTH,
.disabledTooltip = "Override redundant for health source." } })
.DefaultValue(true)
.Tooltip(
"Shows red color when health is critical, otherwise displays according to color source."));
} }
ImGui::TreePop(); ImGui::TreePop();
} }
@ -1234,12 +1243,9 @@ void SohInputEditorWindow::DrawGyroSection(uint8_t port) {
} }
} }
const ImGuiTableFlags PANEL_TABLE_FLAGS = const ImGuiTableFlags PANEL_TABLE_FLAGS = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV;
ImGuiTableFlags_BordersH |
ImGuiTableFlags_BordersV;
const ImGuiTableColumnFlags PANEL_TABLE_COLUMN_FLAGS = const ImGuiTableColumnFlags PANEL_TABLE_COLUMN_FLAGS =
ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
ImGuiTableColumnFlags_NoSort;
namespace TableHelper { namespace TableHelper {
void InitHeader(bool has_header = true) { void InitHeader(bool has_header = true) {
@ -1264,7 +1270,7 @@ namespace TableHelper {
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
} }
} } // namespace TableHelper
void SohInputEditorWindow::addButtonName(N64ButtonMask mask, const char* name) { void SohInputEditorWindow::addButtonName(N64ButtonMask mask, const char* name) {
buttons.push_back(std::make_pair(mask, name)); buttons.push_back(std::make_pair(mask, name));
@ -1344,29 +1350,47 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() {
void SohInputEditorWindow::DrawCameraControlPanel() { void SohInputEditorWindow::DrawCameraControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos(); ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
CVarCheckbox("Enable Mouse Controls", CVAR_SETTING("EnableMouse"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox(
"Enable Mouse Controls", CVAR_SETTING("EnableMouse"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Allows for using the mouse to control the camera (must enable Free Look), " .Tooltip("Allows for using the mouse to control the camera (must enable Free Look), "
"aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)")); "aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)"));
Ship::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail());
CVarCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim"),
CheckboxOptions()
.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"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson"),
CheckboxOptions()
.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"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming")); .Tooltip("Inverts the Camera X Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"));
CVarCheckbox("Invert Aiming Y Axis", CVAR_SETTING("Controls.InvertAimingYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true) CVarCheckbox("Invert Aiming Y Axis", CVAR_SETTING("Controls.InvertAimingYAxis"),
CheckboxOptions()
.Color(THEME_COLOR)
.DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming")); .Tooltip("Inverts the Camera Y Axis in:\n-First-Person/C-Up view\n-Weapon Aiming"));
CVarCheckbox("Invert Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingXAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true) CVarCheckbox("Invert Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingXAxis"),
.Tooltip("Inverts the Shield Aiming X Axis")); CheckboxOptions().Color(THEME_COLOR).DefaultValue(true).Tooltip("Inverts the Shield Aiming X Axis"));
CVarCheckbox("Invert Shield Aiming Y Axis", CVAR_SETTING("Controls.InvertShieldAimingYAxis"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Invert Shield Aiming Y Axis", CVAR_SETTING("Controls.InvertShieldAimingYAxis"),
.Tooltip("Inverts the Shield Aiming Y Axis")); CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Shield Aiming Y Axis"));
CVarCheckbox("Invert Z-Weapon Aiming Y Axis", CVAR_SETTING("Controls.InvertZAimingYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true) CVarCheckbox("Invert Z-Weapon Aiming Y Axis", CVAR_SETTING("Controls.InvertZAimingYAxis"),
CheckboxOptions()
.Color(THEME_COLOR)
.DefaultValue(true)
.Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming")); .Tooltip("Inverts the Camera Y Axis in:\n-Z-Weapon Aiming"));
CVarCheckbox("Disable Auto-Centering in First-Person View", CVAR_SETTING("DisableFirstPersonAutoCenterView"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Disable Auto-Centering in First-Person View", CVAR_SETTING("DisableFirstPersonAutoCenterView"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming")); .Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"));
if (CVarCheckbox("Enable Custom Aiming/First-Person sensitivity", CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), CheckboxOptions().Color(THEME_COLOR))) { if (CVarCheckbox("Enable Custom Aiming/First-Person sensitivity",
CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), CheckboxOptions().Color(THEME_COLOR))) {
if (!CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) { if (!CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) {
CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.X")); CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.X"));
CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.Y")); CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.Y"));
@ -1374,10 +1398,24 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
} }
} }
if (CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) { if (CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) {
CVarSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FirstPersonCameraSensitivity.X"), CVarSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%",
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); CVAR_SETTING("FirstPersonCameraSensitivity.X"),
CVarSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FirstPersonCameraSensitivity.Y"), FloatSliderOptions()
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); .Color(THEME_COLOR)
.IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Aiming/First-Person Vertical Sensitivity: %.0f %%",
CVAR_SETTING("FirstPersonCameraSensitivity.Y"),
FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
} }
Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0);
@ -1385,19 +1423,37 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
Ship::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail());
CVarCheckbox("Free Look", CVAR_SETTING("FreeLook.Enabled"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox(
"Free Look", CVAR_SETTING("FreeLook.Enabled"),
CheckboxOptions()
.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."));
CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"),
.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("Invert Camera Y Axis", CVAR_SETTING("FreeLook.InvertYAxis"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true) CVarCheckbox(
.Tooltip("Inverts the Camera Y Axis in:\n-Free look")); "Invert Camera Y Axis", CVAR_SETTING("FreeLook.InvertYAxis"),
CheckboxOptions().Color(THEME_COLOR).DefaultValue(true).Tooltip("Inverts the Camera Y Axis in:\n-Free look"));
CVarSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.X"), CVarSliderFloat("Third-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.X"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.Y"), CVarSliderFloat("Third-Person Vertical Sensitivity: %.0f %%", CVAR_SETTING("FreeLook.CameraSensitivity.Y"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
CVarSliderInt("Camera Distance: %d", CVAR_SETTING("FreeLook.MaxCameraDistance"), IntSliderOptions().Color(THEME_COLOR).Min(100).Max(900).DefaultValue(185).ShowButtons(true)); .Color(THEME_COLOR)
CVarSliderInt("Camera Transition Speed: %d", CVAR_SETTING("FreeLook.TransitionSpeed"), IntSliderOptions().Color(THEME_COLOR).Min(0).Max(900).DefaultValue(25).ShowButtons(true)); .IsPercentage()
.Min(0.01f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderInt("Camera Distance: %d", CVAR_SETTING("FreeLook.MaxCameraDistance"),
IntSliderOptions().Color(THEME_COLOR).Min(100).Max(900).DefaultValue(185).ShowButtons(true));
CVarSliderInt("Camera Transition Speed: %d", CVAR_SETTING("FreeLook.TransitionSpeed"),
IntSliderOptions().Color(THEME_COLOR).Min(0).Max(900).DefaultValue(25).ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0);
} }
@ -1405,16 +1461,25 @@ void SohInputEditorWindow::DrawDpadControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos(); ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail());
CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"),
.Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold C-Up to equip instead of navigate")); CheckboxOptions()
CVarCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText"), CheckboxOptions().Color(THEME_COLOR) .Color(THEME_COLOR)
.Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry screens with the D-pad")); .Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold "
"C-Up to equip instead of navigate"));
CVarCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry "
"screens with the D-pad"));
if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) { if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) {
ImGui::BeginDisabled(); ImGui::BeginDisabled();
} }
CVarCheckbox("D-pad hold change", CVAR_SETTING("DpadHoldChange"), CheckboxOptions().Color(THEME_COLOR).DefaultValue(true) CVarCheckbox("D-pad hold change", CVAR_SETTING("DpadHoldChange"),
CheckboxOptions()
.Color(THEME_COLOR)
.DefaultValue(true)
.Tooltip("The cursor will only move a single space no matter how long a D-pad direction is held")); .Tooltip("The cursor will only move a single space no matter how long a D-pad direction is held"));
if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) { if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) {
@ -1536,24 +1601,52 @@ void SohInputEditorWindow::DrawLinkTab() {
DrawButtonLine("M2", portIndex, BTN_CUSTOM_MODIFIER2); DrawButtonLine("M2", portIndex, BTN_CUSTOM_MODIFIER2);
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
CVarCheckbox("Enable speed modifiers", CVAR_SETTING("WalkModifier.Enabled"), CheckboxOptions().Color(THEME_COLOR) CVarCheckbox("Enable speed modifiers", CVAR_SETTING("WalkModifier.Enabled"),
CheckboxOptions()
.Color(THEME_COLOR)
.Tooltip("Hold the assigned button to change the maximum walking or swimming speed")); .Tooltip("Hold the assigned button to change the maximum walking or swimming speed"));
if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0)) { if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0)) {
UIWidgets::Spacer(5); UIWidgets::Spacer(5);
Ship::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("Speed Modifier", ImGui::GetContentRegionAvail());
CVarCheckbox("Toggle modifier instead of holding", CVAR_SETTING("WalkModifier.SpeedToggle"), CheckboxOptions().Color(THEME_COLOR)); CVarCheckbox("Toggle modifier instead of holding", CVAR_SETTING("WalkModifier.SpeedToggle"),
CheckboxOptions().Color(THEME_COLOR));
Ship::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("Walk Modifier", ImGui::GetContentRegionAvail());
CVarCheckbox("Don't affect jump distance/velocity", CVAR_SETTING("WalkModifier.DoesntChangeJump"), CheckboxOptions().Color(THEME_COLOR)); CVarCheckbox("Don't affect jump distance/velocity", CVAR_SETTING("WalkModifier.DoesntChangeJump"),
CheckboxOptions().Color(THEME_COLOR));
CVarSliderFloat("Walk Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.Mapping1"), CVarSliderFloat("Walk Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.Mapping1"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Walk Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.Mapping2"), CVarSliderFloat("Walk Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.Mapping2"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0);
Ship::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail()); Ship::GuiWindow::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail());
CVarSliderFloat("Swim Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping1"), CVarSliderFloat("Swim Modifier 1: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping1"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
CVarSliderFloat("Swim Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping2"), CVarSliderFloat("Swim Modifier 2: %.0f %%", CVAR_SETTING("WalkModifier.SwimMapping2"),
FloatSliderOptions().Color(THEME_COLOR).IsPercentage().Min(0.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true)); FloatSliderOptions()
.Color(THEME_COLOR)
.IsPercentage()
.Min(0.0f)
.Max(5.0f)
.DefaultValue(1.0f)
.ShowButtons(true));
Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0);
Ship::GuiWindow::EndGroupPanel(0); Ship::GuiWindow::EndGroupPanel(0);
} }
@ -1755,7 +1848,8 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) {
} }
PopStyleButton(); PopStyleButton();
if (ImGui::BeginPopupModal("Set Defaults for Gamepad (SDL)", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { if (ImGui::BeginPopupModal("Set Defaults for Gamepad (SDL)", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("This will clear all existing mappings for\nGamepad (SDL) on port %d.\n\nContinue?", portIndex + 1); ImGui::Text("This will clear all existing mappings for\nGamepad (SDL) on port %d.\n\nContinue?",
portIndex + 1);
PushStyleButton(THEME_COLOR); PushStyleButton(THEME_COLOR);
if (ImGui::Button("Cancel")) { if (ImGui::Button("Cancel")) {
shouldClose = true; shouldClose = true;

View file

@ -41,7 +41,8 @@ class SohInputEditorWindow : public Ship::GuiWindow {
void DrawButtonLineEditMappingButton(uint8_t port, N64ButtonMask bitmask, std::string id); void DrawButtonLineEditMappingButton(uint8_t port, N64ButtonMask bitmask, std::string id);
void DrawButtonLineAddMappingButton(uint8_t port, N64ButtonMask bitmask); void DrawButtonLineAddMappingButton(uint8_t port, N64ButtonMask bitmask);
void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction, std::string id); void DrawStickDirectionLineEditMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction,
std::string id);
void DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction); void DrawStickDirectionLineAddMappingButton(uint8_t port, uint8_t stick, Ship::Direction direction);
void DrawStickSection(uint8_t port, uint8_t stick, int32_t id, ImVec4 color); void DrawStickSection(uint8_t port, uint8_t stick, int32_t id, ImVec4 color);

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,9 @@
#pragma once #pragma once
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
// Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to reset/randomize // Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to
// every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in `DrawCosmeticsEditor` // reset/randomize every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in
// `DrawCosmeticsEditor`
typedef enum { typedef enum {
COSMETICS_GROUP_LINK, COSMETICS_GROUP_LINK,
COSMETICS_GROUP_MIRRORSHIELD, COSMETICS_GROUP_MIRRORSHIELD,
@ -50,7 +51,8 @@ typedef struct {
static float TablesCellsWidth = 300.0f; static float TablesCellsWidth = 300.0f;
static ImGuiTableColumnFlags FlagsTable = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV; static ImGuiTableColumnFlags FlagsTable = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV;
static ImGuiTableColumnFlags FlagsCell = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort; static ImGuiTableColumnFlags FlagsCell =
ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
void CosmeticsEditor_RandomizeAll(); void CosmeticsEditor_RandomizeAll();
void CosmeticsEditor_RandomizeGroup(CosmeticGroup group); void CosmeticsEditor_RandomizeGroup(CosmeticGroup group);

View file

@ -70,7 +70,8 @@ extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToD
gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, PRIMITIVE, ENV_ALPHA, TEXEL0, 0, 0, 0, TEXEL0, PRIMITIVE, ENVIRONMENT, gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, PRIMITIVE, ENV_ALPHA, TEXEL0, 0, 0, 0, TEXEL0, PRIMITIVE, ENVIRONMENT,
COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0); COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0);
if (CVarGetInteger(CVAR_COSMETIC("Title.NintendoLogo.Changed"), 0)) { if (CVarGetInteger(CVAR_COSMETIC("Title.NintendoLogo.Changed"), 0)) {
Color_RGB8 nintendoLogoColor = CVarGetColor24(CVAR_COSMETIC("Title.NintendoLogo.Value"), Color_RGB8{0, 0, 255}); Color_RGB8 nintendoLogoColor =
CVarGetColor24(CVAR_COSMETIC("Title.NintendoLogo.Value"), Color_RGB8{ 0, 0, 255 });
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
gDPSetEnvColor(POLY_OPA_DISP++, nintendoLogoColor.r, nintendoLogoColor.g, nintendoLogoColor.b, 128); gDPSetEnvColor(POLY_OPA_DISP++, nintendoLogoColor.r, nintendoLogoColor.g, nintendoLogoColor.b, 128);
} else { } else {
@ -81,14 +82,14 @@ extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToD
gDPLoadMultiBlock(POLY_OPA_DISP++, nintendo_rogo_static_Tex_001800, 0x100, 1, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0, gDPLoadMultiBlock(POLY_OPA_DISP++, nintendo_rogo_static_Tex_001800, 0x100, 1, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 5, 5, 2, 11); G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 5, 5, 2, 11);
for (idx = 0, y = 94; idx < 16; idx++, y += 2) for (idx = 0, y = 94; idx < 16; idx++, y += 2) {
{ gDPLoadMultiTile(
gDPLoadMultiTile(POLY_OPA_DISP++, (logoToDraw == LOGO_TO_DRAW_N64) ? nintendo_rogo_static_Tex_000000 : nintendo_rogo_static_Tex_LUS_000000, 0, G_TX_RENDERTILE, G_IM_FMT_I, G_IM_SIZ_8b, 192, 32, POLY_OPA_DISP++,
0, idx * 2, 192 - 1, (idx + 1) * 2 - 1, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, (logoToDraw == LOGO_TO_DRAW_N64) ? nintendo_rogo_static_Tex_000000 : nintendo_rogo_static_Tex_LUS_000000, 0,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); G_TX_RENDERTILE, G_IM_FMT_I, G_IM_SIZ_8b, 192, 32, 0, idx * 2, 192 - 1, (idx + 1) * 2 - 1, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gDPSetTileSize(POLY_OPA_DISP++, 0, 0, 0, (192 - 1) << G_TEXTURE_IMAGE_FRAC, gDPSetTileSize(POLY_OPA_DISP++, 0, 0, 0, (192 - 1) << G_TEXTURE_IMAGE_FRAC, (2 - 1) << G_TEXTURE_IMAGE_FRAC);
(2 - 1) << G_TEXTURE_IMAGE_FRAC);
gDPSetTileSize(POLY_OPA_DISP++, 1, titleContext->uls, (titleContext->ult & 0x7F) - idx * 4, 0, 0); gDPSetTileSize(POLY_OPA_DISP++, 1, titleContext->uls, (titleContext->ult & 0x7F) - idx * 4, 0, 0);
gSPTextureRectangle(POLY_OPA_DISP++, 388, y << 2, 1156, (y + 2) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); gSPTextureRectangle(POLY_OPA_DISP++, 388, y << 2, 1156, (y + 2) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
@ -99,8 +100,8 @@ extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToD
f32 scale = 0.4f; f32 scale = 0.4f;
gSPSegment(POLY_OPA_DISP++, 0x08, gSPSegment(POLY_OPA_DISP++, 0x08,
(uintptr_t)Gfx_TwoTexScroll(titleContext->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1, (uintptr_t)Gfx_TwoTexScroll(titleContext->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1, 0,
0, (1 * -2) % 128, 32, 32)); (1 * -2) % 128, 32, 32));
Matrix_Translate(0.0f, -10.0f, 0.0f, MTXMODE_APPLY); Matrix_Translate(0.0f, -10.0f, 0.0f, MTXMODE_APPLY);
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);

View file

@ -38,9 +38,12 @@ void UpdateNoMSPatch() {
std::string patchName = "adultNoMS." + std::to_string(3) + "." + std::to_string(i); std::string patchName = "adultNoMS." + std::to_string(3) + "." + std::to_string(i);
ResourceMgr_PatchGfxByName(gLinkAdultMirrorShieldSwordAndSheathFarDL, patchName.c_str(), i, gsDPNoOp()); ResourceMgr_PatchGfxByName(gLinkAdultMirrorShieldSwordAndSheathFarDL, patchName.c_str(), i, gsDPNoOp());
} }
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathNearDL, "adultNoMSHylianShield1", 75, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathNearDL, "adultNoMSHylianShield1", 75,
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathFarDL, "adultNoMSHylianShield2", 71, gsSPEndDisplayList()); gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathNearDL, "adultNoMasterSword1", 2, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathFarDL, "adultNoMSHylianShield2", 71,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathNearDL, "adultNoMasterSword1", 2,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathFarDL, "adultNoMasterSword2", 2, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathFarDL, "adultNoMasterSword2", 2, gsSPEndDisplayList());
} else { } else {
// Unpatching if conditions are not met // Unpatching if conditions are not met
@ -86,7 +89,8 @@ void RegisterNoMasterSword() {
int32_t startMode = va_arg(args, int32_t); int32_t startMode = va_arg(args, int32_t);
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (startMode == PLAYER_START_MODE_TIME_TRAVEL && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) { if (startMode == PLAYER_START_MODE_TIME_TRAVEL &&
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) {
// don't run the vanilla startMode func // don't run the vanilla startMode func
*should = false; *should = false;

View file

@ -19,10 +19,8 @@ typedef struct {
} DListPatchInfo; } DListPatchInfo;
static DListPatchInfo freezardBodyDListPatchInfos[] = { static DListPatchInfo freezardBodyDListPatchInfos[] = {
{ gFreezardIntactDL, 5 }, { gFreezardIntactDL, 5 }, { gFreezardTopRightHornChippedDL, 5 },
{ gFreezardTopRightHornChippedDL, 5 }, { gFreezardHeadChippedDL, 5 }, { gFreezardIceTriangleDL, 5 },
{ gFreezardHeadChippedDL, 5 },
{ gFreezardIceTriangleDL, 5 },
{ gFreezardIceRockDL, 5 }, { gFreezardIceRockDL, 5 },
}; };
@ -339,7 +337,8 @@ void PatchMirroredSoldOutGI() {
void PatchMirroredSunSongEtching() { void PatchMirroredSunSongEtching() {
// Only using these strings for graphics patching lookup, we don't need aligned assets here // Only using these strings for graphics patching lookup, we don't need aligned assets here
static const char gRoyalGraveBackRoomDL[] = "__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2DL_005040"; static const char gRoyalGraveBackRoomDL[] = "__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2DL_005040";
static const char gRoyalGraveBackRoomSongVtx[] = "__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2Vtx_004F80"; static const char gRoyalGraveBackRoomSongVtx[] =
"__OTR__scenes/shared/hakaana_ouke_scene/hakaana_ouke_room_2Vtx_004F80";
static Vtx* mirroredSunSongVtx; static Vtx* mirroredSunSongVtx;
@ -365,7 +364,8 @@ void PatchMirroredSunSongEtching() {
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_1", 13, mirroredSunSongTex[1]); ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_1", 13, mirroredSunSongTex[1]);
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_2", 17, mirroredSunSongTex[5]); ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_2", 17, mirroredSunSongTex[5]);
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_1", 24, gsSPVertex(mirroredSunSongVtx, 4, 0)); ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_1", 24,
gsSPVertex(mirroredSunSongVtx, 4, 0));
// noop as the original vertex command is 128 bit wide // noop as the original vertex command is 128 bit wide
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_2", 25, gsSPNoOp()); ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_2", 25, gsSPNoOp());
} else { } else {

View file

@ -16,35 +16,24 @@ static const std::unordered_map<std::string, char> textBoxSpecialCharacters = {
{ "è", 0x95 }, { "é", 0x96 }, { "ê", 0x97 }, { "ë", 0x98 }, { "ï", 0x99 }, { "ô", 0x9A }, { "ö", 0x9B }, { "è", 0x95 }, { "é", 0x96 }, { "ê", 0x97 }, { "ë", 0x98 }, { "ï", 0x99 }, { "ô", 0x9A }, { "ö", 0x9B },
{ "ù", 0x9C }, { "û", 0x9D }, { "ü", 0x9E } { "ù", 0x9C }, { "û", 0x9D }, { "ü", 0x9E }
}; };
static const std::unordered_map<std::string, std::string> percentColors = { { "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN }, static const std::unordered_map<std::string, std::string> percentColors = {
{ "b", QM_BLUE }, { "c", QM_LBLUE }, { "p", QM_PINK }, { "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN }, { "b", QM_BLUE },
{ "y", QM_YELLOW }, { "B", QM_BLACK }, }; { "c", QM_LBLUE }, { "p", QM_PINK }, { "y", QM_YELLOW }, { "B", QM_BLACK },
};
static const std::unordered_map<std::string, std::string> colorToPercent = { { QM_WHITE, "%w" }, { QM_RED, "%r"}, { QM_GREEN, "%g" }, static const std::unordered_map<std::string, std::string> colorToPercent = {
{ QM_BLUE, "%b" }, { QM_LBLUE, "%c"}, { QM_PINK, "%p" }, { QM_WHITE, "%w" }, { QM_RED, "%r" }, { QM_GREEN, "%g" }, { QM_BLUE, "%b" },
{ QM_YELLOW, "%y" }, { QM_BLACK, "%B" }, }; { QM_LBLUE, "%c" }, { QM_PINK, "%p" }, { QM_YELLOW, "%y" }, { QM_BLACK, "%B" },
};
static const std::unordered_map<std::string, ItemID> altarIcons = { static const std::unordered_map<std::string, ItemID> altarIcons = {
{ "0", ITEM_KOKIRI_EMERALD }, { "0", ITEM_KOKIRI_EMERALD }, { "1", ITEM_GORON_RUBY }, { "2", ITEM_ZORA_SAPPHIRE },
{ "1", ITEM_GORON_RUBY }, { "8", ITEM_MEDALLION_LIGHT }, { "3", ITEM_MEDALLION_FOREST }, { "4", ITEM_MEDALLION_FIRE },
{ "2", ITEM_ZORA_SAPPHIRE }, { "5", ITEM_MEDALLION_WATER }, { "6", ITEM_MEDALLION_SPIRIT }, { "7", ITEM_MEDALLION_SHADOW },
{ "8", ITEM_MEDALLION_LIGHT }, { "l", ITEM_ARROW_LIGHT }, { "b", ITEM_KEY_BOSS }, { "o", ITEM_SWORD_MASTER },
{ "3", ITEM_MEDALLION_FOREST }, { "c", ITEM_OCARINA_FAIRY }, { "i", ITEM_OCARINA_TIME }, { "L", ITEM_BOW_ARROW_LIGHT },
{ "4", ITEM_MEDALLION_FIRE }, { "k", ITEM_TUNIC_KOKIRI }, { "m", ITEM_DUNGEON_MAP }, { "C", ITEM_COMPASS },
{ "5", ITEM_MEDALLION_WATER }, { "s", ITEM_SKULL_TOKEN }, { "g", ITEM_MASK_GORON },
{ "6", ITEM_MEDALLION_SPIRIT },
{ "7", ITEM_MEDALLION_SHADOW },
{ "l", ITEM_ARROW_LIGHT },
{ "b", ITEM_KEY_BOSS },
{ "o", ITEM_SWORD_MASTER },
{ "c", ITEM_OCARINA_FAIRY },
{ "i", ITEM_OCARINA_TIME },
{ "L", ITEM_BOW_ARROW_LIGHT },
{ "k", ITEM_TUNIC_KOKIRI },
{ "m", ITEM_DUNGEON_MAP },
{ "C", ITEM_COMPASS },
{ "s", ITEM_SKULL_TOKEN },
{ "g", ITEM_MASK_GORON },
}; };
static std::map<std::string, int> pixelWidthTable = { static std::map<std::string, int> pixelWidthTable = {
@ -83,8 +72,9 @@ CustomMessage::CustomMessage(std::string english_, std::string german_, std::str
messages[LANGUAGE_FRA] = std::move(french_); messages[LANGUAGE_FRA] = std::move(french_);
} }
CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, std::vector<std::string> colors_, CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_,
std::vector<bool> capital_, TextBoxType type_, TextBoxPosition position_) { std::vector<std::string> colors_, std::vector<bool> capital_, TextBoxType type_,
TextBoxPosition position_) {
messages[LANGUAGE_ENG] = std::move(english_); messages[LANGUAGE_ENG] = std::move(english_);
messages[LANGUAGE_GER] = std::move(german_); messages[LANGUAGE_GER] = std::move(german_);
messages[LANGUAGE_FRA] = std::move(french_); messages[LANGUAGE_FRA] = std::move(french_);
@ -99,7 +89,8 @@ CustomMessage::CustomMessage(std::string english_, TextBoxType type_, TextBoxPos
messages[LANGUAGE_ENG] = std::move(english_); messages[LANGUAGE_ENG] = std::move(english_);
} }
CustomMessage::CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_, TextBoxType type_, TextBoxPosition position_){ CustomMessage::CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_,
TextBoxType type_, TextBoxPosition position_) {
messages[LANGUAGE_ENG] = std::move(english_); messages[LANGUAGE_ENG] = std::move(english_);
colors = colors_; colors = colors_;
capital = capital_; capital = capital_;
@ -151,7 +142,6 @@ CustomMessage CustomMessage::LoadVanillaMessageTableEntry(uint16_t textId) {
return CustomMessage(); return CustomMessage();
} }
const std::string CustomMessage::GetEnglish(MessageFormat format) const { const std::string CustomMessage::GetEnglish(MessageFormat format) const {
return GetForLanguage(LANGUAGE_ENG, format); return GetForLanguage(LANGUAGE_ENG, format);
} }
@ -231,12 +221,12 @@ CustomMessage CustomMessage::operator+(const CustomMessage& right) const {
newCapital.insert(newCapital.end(), right.GetCapital().begin(), right.GetCapital().end()); newCapital.insert(newCapital.end(), right.GetCapital().begin(), right.GetCapital().end());
return CustomMessage(messages[LANGUAGE_ENG] + right.GetEnglish(MF_RAW), return CustomMessage(messages[LANGUAGE_ENG] + right.GetEnglish(MF_RAW),
messages[LANGUAGE_GER] + right.GetGerman(MF_RAW), messages[LANGUAGE_GER] + right.GetGerman(MF_RAW),
messages[LANGUAGE_FRA] + right.GetFrench(MF_RAW), messages[LANGUAGE_FRA] + right.GetFrench(MF_RAW), newColors, newCapital, type, position);
newColors, newCapital, type, position);
} }
CustomMessage CustomMessage::operator+(const std::string& right) const { CustomMessage CustomMessage::operator+(const std::string& right) const {
return CustomMessage(messages[LANGUAGE_ENG] + right, messages[LANGUAGE_GER] + right, messages[LANGUAGE_FRA] + right); return CustomMessage(messages[LANGUAGE_ENG] + right, messages[LANGUAGE_GER] + right,
messages[LANGUAGE_FRA] + right);
} }
void CustomMessage::operator+=(const CustomMessage& right) { void CustomMessage::operator+=(const CustomMessage& right) {
@ -399,7 +389,8 @@ static size_t NextLineLength(const std::string* textStr, const size_t lastNewlin
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)]; totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)];
nextPosJump = 2; nextPosJump = 2;
} else { } else {
SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + textStr->substr(currentPos, 2)); SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" +
textStr->substr(currentPos, 2));
SPDLOG_DEBUG("Full string: " + *textStr); SPDLOG_DEBUG("Full string: " + *textStr);
nextPosJump = 1; nextPosJump = 1;
} }
@ -586,7 +577,6 @@ void CustomMessage::InsertNumber(uint8_t num){
Replace("[[d]]", std::to_string(num)); Replace("[[d]]", std::to_string(num));
} }
void CustomMessage::Capitalize() { void CustomMessage::Capitalize() {
for (std::string str : messages) { for (std::string str : messages) {
(str)[0] = std::toupper((str)[0]); (str)[0] = std::toupper((str)[0]);

View file

@ -41,10 +41,13 @@ class CustomMessage {
CustomMessage() = default; CustomMessage() = default;
CustomMessage(std::string english_, std::string german_, std::string french_, CustomMessage(std::string english_, std::string german_, std::string french_,
TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, std::string german_, std::string french_, std::vector<std::string> colors_, std::vector<bool> capital_ = {}, CustomMessage(std::string english_, std::string german_, std::string french_, std::vector<std::string> colors_,
std::vector<bool> capital_ = {}, TextBoxType type_ = TEXTBOX_TYPE_BLACK,
TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK,
TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
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(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_ = {}, 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);
static CustomMessage LoadVanillaMessageTableEntry(uint16_t textId); static CustomMessage LoadVanillaMessageTableEntry(uint16_t textId);

View file

@ -36,10 +36,17 @@ extern PlayState* gPlayState;
#define CMD_REGISTER Ship::Context::GetInstance()->GetConsole()->AddCommand #define CMD_REGISTER Ship::Context::GetInstance()->GetConsole()->AddCommand
// TODO: Commands should be using the output passed in. // TODO: Commands should be using the output passed in.
#define ERROR_MESSAGE std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->SendErrorMessage #define ERROR_MESSAGE \
#define INFO_MESSAGE std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->SendInfoMessage std::reinterpret_pointer_cast<Ship::ConsoleWindow>( \
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console")) \
->SendErrorMessage
#define INFO_MESSAGE \
std::reinterpret_pointer_cast<Ship::ConsoleWindow>( \
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console")) \
->SendInfoMessage
static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) { if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) {
ERROR_MESSAGE("Not enough arguments passed to actorspawn"); ERROR_MESSAGE("Not enough arguments passed to actorspawn");
return 1; return 1;
@ -100,7 +107,8 @@ static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std:
return 0; return 0;
} }
static bool KillPlayerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&, std::string* output) { static bool KillPlayerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&,
std::string* output) {
GameInteractionEffectBase* effect = new GameInteractionEffect::SetPlayerHealth(); GameInteractionEffectBase* effect = new GameInteractionEffect::SetPlayerHealth();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0] = 0; dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0] = 0;
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
@ -113,7 +121,8 @@ static bool KillPlayerHandler(std::shared_ptr<Ship::Console> Console, const std:
} }
} }
static bool SetPlayerHealthHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool SetPlayerHealthHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -144,7 +153,8 @@ static bool SetPlayerHealthHandler(std::shared_ptr<Ship::Console> Console, const
} }
} }
static bool LoadSceneHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&, std::string* output) { static bool LoadSceneHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&,
std::string* output) {
gSaveContext.respawnFlag = 0; gSaveContext.respawnFlag = 0;
gSaveContext.seqId = 0xFF; gSaveContext.seqId = 0xFF;
gSaveContext.gameMode = GAMEMODE_NORMAL; gSaveContext.gameMode = GAMEMODE_NORMAL;
@ -152,7 +162,8 @@ static bool LoadSceneHandler(std::shared_ptr<Ship::Console> Console, const std::
return 0; return 0;
} }
static bool RupeeHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool RupeeHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
return 1; return 1;
} }
@ -160,8 +171,7 @@ static bool RupeeHandler(std::shared_ptr<Ship::Console> Console, const std::vect
int rupeeAmount; int rupeeAmount;
try { try {
rupeeAmount = std::stoi(args[1]); rupeeAmount = std::stoi(args[1]);
} } catch (std::invalid_argument const& ex) {
catch (std::invalid_argument const& ex) {
ERROR_MESSAGE("[SOH] Rupee count must be an integer."); ERROR_MESSAGE("[SOH] Rupee count must be an integer.");
return 1; return 1;
} }
@ -177,7 +187,8 @@ static bool RupeeHandler(std::shared_ptr<Ship::Console> Console, const std::vect
return 0; return 0;
} }
static bool SetPosHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string> args, std::string* output) { static bool SetPosHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string> args,
std::string* output) {
if (gPlayState == nullptr) { if (gPlayState == nullptr) {
ERROR_MESSAGE("PlayState == nullptr"); ERROR_MESSAGE("PlayState == nullptr");
return 1; return 1;
@ -186,8 +197,7 @@ static bool SetPosHandler(std::shared_ptr<Ship::Console> Console, const std::vec
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (args.size() == 1) { if (args.size() == 1) {
INFO_MESSAGE("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, INFO_MESSAGE("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, player->actor.world.pos.y,
player->actor.world.pos.y,
player->actor.world.pos.z); player->actor.world.pos.z);
return 0; return 0;
} }
@ -198,8 +208,7 @@ static bool SetPosHandler(std::shared_ptr<Ship::Console> Console, const std::vec
player->actor.world.pos.y = std::stof(args[2]); player->actor.world.pos.y = std::stof(args[2]);
player->actor.world.pos.z = std::stof(args[3]); player->actor.world.pos.z = std::stof(args[3]);
INFO_MESSAGE("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, INFO_MESSAGE("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, player->actor.world.pos.y,
player->actor.world.pos.y,
player->actor.world.pos.z); player->actor.world.pos.z);
return 0; return 0;
} }
@ -216,13 +225,12 @@ static bool ResetHandler(std::shared_ptr<Ship::Console> Console, std::vector<std
} }
const static std::map<std::string, uint16_t> ammoItems{ const static std::map<std::string, uint16_t> ammoItems{
{ "sticks", ITEM_STICK }, { "nuts", ITEM_NUT }, { "sticks", ITEM_STICK }, { "nuts", ITEM_NUT }, { "bombs", ITEM_BOMB }, { "seeds", ITEM_SLINGSHOT },
{ "bombs", ITEM_BOMB }, { "seeds", ITEM_SLINGSHOT }, { "arrows", ITEM_BOW }, { "bombchus", ITEM_BOMBCHU }, { "beans", ITEM_BEAN },
{ "arrows", ITEM_BOW }, { "bombchus", ITEM_BOMBCHU },
{ "beans", ITEM_BEAN },
}; };
static bool AddAmmoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool AddAmmoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 3) { if (args.size() < 3) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -243,7 +251,8 @@ static bool AddAmmoHandler(std::shared_ptr<Ship::Console> Console, const std::ve
const auto& it = ammoItems.find(args[1]); const auto& it = ammoItems.find(args[1]);
if (it == ammoItems.end()) { if (it == ammoItems.end()) {
ERROR_MESSAGE("Invalid ammo type. Options are 'sticks', 'nuts', 'bombs', 'seeds', 'arrows', 'bombchus' and 'beans'"); ERROR_MESSAGE(
"Invalid ammo type. Options are 'sticks', 'nuts', 'bombs', 'seeds', 'arrows', 'bombchus' and 'beans'");
return 1; return 1;
} }
@ -261,7 +270,8 @@ static bool AddAmmoHandler(std::shared_ptr<Ship::Console> Console, const std::ve
} }
} }
static bool TakeAmmoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool TakeAmmoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 3) { if (args.size() < 3) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -302,13 +312,22 @@ static bool TakeAmmoHandler(std::shared_ptr<Ship::Console> Console, const std::v
} }
const static std::map<std::string, uint16_t> bottleItems{ const static std::map<std::string, uint16_t> bottleItems{
{ "green_potion", ITEM_POTION_GREEN }, { "red_potion", ITEM_POTION_RED }, { "blue_potion", ITEM_POTION_BLUE }, { "green_potion", ITEM_POTION_GREEN },
{ "milk", ITEM_MILK }, { "half_milk", ITEM_MILK_HALF }, { "fairy", ITEM_FAIRY }, { "red_potion", ITEM_POTION_RED },
{ "bugs", ITEM_BUG }, { "fish", ITEM_FISH }, { "poe", ITEM_POE }, { "blue_potion", ITEM_POTION_BLUE },
{ "big_poe", ITEM_BIG_POE }, { "blue_fire", ITEM_BLUE_FIRE }, { "rutos_letter", ITEM_LETTER_RUTO }, { "milk", ITEM_MILK },
{ "half_milk", ITEM_MILK_HALF },
{ "fairy", ITEM_FAIRY },
{ "bugs", ITEM_BUG },
{ "fish", ITEM_FISH },
{ "poe", ITEM_POE },
{ "big_poe", ITEM_BIG_POE },
{ "blue_fire", ITEM_BLUE_FIRE },
{ "rutos_letter", ITEM_LETTER_RUTO },
}; };
static bool BottleHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool BottleHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 3) { if (args.size() < 3) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -340,7 +359,8 @@ static bool BottleHandler(std::shared_ptr<Ship::Console> Console, const std::vec
return 0; return 0;
} }
static bool BHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool BHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -350,7 +370,8 @@ static bool BHandler(std::shared_ptr<Ship::Console> Console, const std::vector<s
return 0; return 0;
} }
static bool ItemHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool ItemHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 3) { if (args.size() < 3) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -361,7 +382,8 @@ static bool ItemHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
return 0; return 0;
} }
static bool GiveItemHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string> args, std::string* output) { static bool GiveItemHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string> args,
std::string* output) {
if (args.size() < 3) { if (args.size() < 3) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -382,7 +404,8 @@ static bool GiveItemHandler(std::shared_ptr<Ship::Console> Console, const std::v
return 0; return 0;
} }
static bool EntranceHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool EntranceHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -404,7 +427,8 @@ static bool EntranceHandler(std::shared_ptr<Ship::Console> Console, const std::v
return 0; return 0;
} }
static bool VoidHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool VoidHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (gPlayState != nullptr) { if (gPlayState != nullptr) {
gSaveContext.respawn[RESPAWN_MODE_DOWN].tempSwchFlags = gPlayState->actorCtx.flags.tempSwch; gSaveContext.respawn[RESPAWN_MODE_DOWN].tempSwchFlags = gPlayState->actorCtx.flags.tempSwch;
gSaveContext.respawn[RESPAWN_MODE_DOWN].tempCollectFlags = gPlayState->actorCtx.flags.tempCollect; gSaveContext.respawn[RESPAWN_MODE_DOWN].tempCollectFlags = gPlayState->actorCtx.flags.tempCollect;
@ -420,7 +444,8 @@ static bool VoidHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
return 0; return 0;
} }
static bool ReloadHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool ReloadHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (gPlayState != nullptr) { if (gPlayState != nullptr) {
gPlayState->nextEntranceIndex = gSaveContext.entranceIndex; gPlayState->nextEntranceIndex = gSaveContext.entranceIndex;
gPlayState->transitionTrigger = TRANS_TRIGGER_START; gPlayState->transitionTrigger = TRANS_TRIGGER_START;
@ -433,11 +458,10 @@ static bool ReloadHandler(std::shared_ptr<Ship::Console> Console, const std::vec
return 0; return 0;
} }
const static std::map<std::string, uint16_t> fw_options { const static std::map<std::string, uint16_t> fw_options{ { "clear", 0 }, { "warp", 1 }, { "backup", 2 } };
{ "clear", 0}, {"warp", 1}, {"backup", 2}
};
static bool FWHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool FWHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -480,8 +504,7 @@ static bool FWHandler(std::shared_ptr<Ship::Console> Console, const std::vector<
} }
break; break;
} }
} } else {
else {
ERROR_MESSAGE("gPlayState == nullptr"); ERROR_MESSAGE("gPlayState == nullptr");
return 1; return 1;
} }
@ -489,7 +512,8 @@ static bool FWHandler(std::shared_ptr<Ship::Console> Console, const std::vector<
return 0; return 0;
} }
static bool FileSelectHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool FileSelectHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (gGameState == nullptr) { if (gGameState == nullptr) {
ERROR_MESSAGE("gGameState == nullptr"); ERROR_MESSAGE("gGameState == nullptr");
return 1; return 1;
@ -501,12 +525,14 @@ static bool FileSelectHandler(std::shared_ptr<Ship::Console> Console, const std:
return 0; return 0;
} }
static bool QuitHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool QuitHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
Ship::Context::GetInstance()->GetWindow()->Close(); Ship::Context::GetInstance()->GetWindow()->Close();
return 0; return 0;
} }
static bool SaveStateHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool SaveStateHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot(); unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot();
const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::SAVE }); const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::SAVE });
@ -522,7 +548,8 @@ static bool SaveStateHandler(std::shared_ptr<Ship::Console> Console, const std::
} }
} }
static bool LoadStateHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool LoadStateHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot(); unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot();
const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::LOAD }); const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::LOAD });
@ -542,10 +569,10 @@ static bool LoadStateHandler(std::shared_ptr<Ship::Console> Console, const std::
default: default:
return 1; return 1;
} }
} }
static bool StateSlotSelectHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool StateSlotSelectHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -565,12 +592,12 @@ static bool StateSlotSelectHandler(std::shared_ptr<Ship::Console> Console, const
} }
OTRGlobals::Instance->gSaveStateMgr->SetCurrentSlot(slot); OTRGlobals::Instance->gSaveStateMgr->SetCurrentSlot(slot);
INFO_MESSAGE("[SOH] Slot %u selected", INFO_MESSAGE("[SOH] Slot %u selected", OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot());
OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot());
return 0; return 0;
} }
static bool InvisibleHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool InvisibleHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -591,13 +618,13 @@ static bool InvisibleHandler(std::shared_ptr<Ship::Console> Console, const std::
INFO_MESSAGE("[SOH] Invisible Link %s", state ? "enabled" : "disabled"); INFO_MESSAGE("[SOH] Invisible Link %s", state ? "enabled" : "disabled");
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not %s Invisible Link.", INFO_MESSAGE("[SOH] Command failed: Could not %s Invisible Link.", state ? "enable" : "disable");
state ? "enable" : "disable");
return 1; return 1;
} }
} }
static bool GiantLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool GiantLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -619,13 +646,13 @@ static bool GiantLinkHandler(std::shared_ptr<Ship::Console> Console, const std::
INFO_MESSAGE("[SOH] Giant Link %s", state ? "enabled" : "disabled"); INFO_MESSAGE("[SOH] Giant Link %s", state ? "enabled" : "disabled");
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not %s Giant Link.", INFO_MESSAGE("[SOH] Command failed: Could not %s Giant Link.", state ? "enable" : "disable");
state ? "enable" : "disable");
return 1; return 1;
} }
} }
static bool MinishLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool MinishLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -647,13 +674,13 @@ static bool MinishLinkHandler(std::shared_ptr<Ship::Console> Console, const std:
INFO_MESSAGE("[SOH] Minish Link %s", state ? "enabled" : "disabled"); INFO_MESSAGE("[SOH] Minish Link %s", state ? "enabled" : "disabled");
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not %s Minish Link.", INFO_MESSAGE("[SOH] Command failed: Could not %s Minish Link.", state ? "enable" : "disable");
state ? "enable" : "disable");
return 1; return 1;
} }
} }
static bool AddHeartContainerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool AddHeartContainerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -684,7 +711,8 @@ static bool AddHeartContainerHandler(std::shared_ptr<Ship::Console> Console, con
} }
} }
static bool RemoveHeartContainerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool RemoveHeartContainerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -715,7 +743,8 @@ static bool RemoveHeartContainerHandler(std::shared_ptr<Ship::Console> Console,
} }
} }
static bool GravityHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool GravityHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -724,7 +753,8 @@ static bool GravityHandler(std::shared_ptr<Ship::Console> Console, const std::ve
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyGravity(); GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyGravity();
try { try {
dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0] = Ship::Math::clamp(std::stoi(args[1], nullptr, 10), GI_GRAVITY_LEVEL_LIGHT, GI_GRAVITY_LEVEL_HEAVY); dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0] =
Ship::Math::clamp(std::stoi(args[1], nullptr, 10), GI_GRAVITY_LEVEL_LIGHT, GI_GRAVITY_LEVEL_HEAVY);
} catch (std::invalid_argument const& ex) { } catch (std::invalid_argument const& ex) {
ERROR_MESSAGE("[SOH] Gravity value must be a number."); ERROR_MESSAGE("[SOH] Gravity value must be a number.");
return 1; return 1;
@ -740,7 +770,8 @@ static bool GravityHandler(std::shared_ptr<Ship::Console> Console, const std::ve
} }
} }
static bool NoUIHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool NoUIHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -762,13 +793,13 @@ static bool NoUIHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
INFO_MESSAGE("[SOH] No UI %s", state ? "enabled" : "disabled"); INFO_MESSAGE("[SOH] No UI %s", state ? "enabled" : "disabled");
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not %s No UI.", INFO_MESSAGE("[SOH] Command failed: Could not %s No UI.", state ? "enable" : "disable");
state ? "enable" : "disable");
return 1; return 1;
} }
} }
static bool FreezeHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool FreezeHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
GameInteractionEffectBase* effect = new GameInteractionEffect::FreezePlayer(); GameInteractionEffectBase* effect = new GameInteractionEffect::FreezePlayer();
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
@ -781,7 +812,8 @@ static bool FreezeHandler(std::shared_ptr<Ship::Console> Console, const std::vec
} }
} }
static bool DefenseModifierHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool DefenseModifierHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -797,7 +829,8 @@ static bool DefenseModifierHandler(std::shared_ptr<Ship::Console> Console, const
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
if (result == GameInteractionEffectQueryResult::Possible) { if (result == GameInteractionEffectQueryResult::Possible) {
INFO_MESSAGE("[SOH] Defense modifier set to %d", dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0]); INFO_MESSAGE("[SOH] Defense modifier set to %d",
dynamic_cast<ParameterizedGameInteractionEffect*>(effect)->parameters[0]);
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not set defense modifier."); INFO_MESSAGE("[SOH] Command failed: Could not set defense modifier.");
@ -805,7 +838,8 @@ static bool DefenseModifierHandler(std::shared_ptr<Ship::Console> Console, const
} }
} }
static bool DamageHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool DamageHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -835,7 +869,8 @@ static bool DamageHandler(std::shared_ptr<Ship::Console> Console, const std::vec
} }
} }
static bool HealHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool HealHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -865,7 +900,8 @@ static bool HealHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
} }
} }
static bool FillMagicHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool FillMagicHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
GameInteractionEffectBase* effect = new GameInteractionEffect::FillMagic(); GameInteractionEffectBase* effect = new GameInteractionEffect::FillMagic();
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
@ -878,7 +914,8 @@ static bool FillMagicHandler(std::shared_ptr<Ship::Console> Console, const std::
} }
} }
static bool EmptyMagicHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool EmptyMagicHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
GameInteractionEffectBase* effect = new GameInteractionEffect::EmptyMagic(); GameInteractionEffectBase* effect = new GameInteractionEffect::EmptyMagic();
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
@ -891,7 +928,8 @@ static bool EmptyMagicHandler(std::shared_ptr<Ship::Console> Console, const std:
} }
} }
static bool NoZHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool NoZHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -913,13 +951,13 @@ static bool NoZHandler(std::shared_ptr<Ship::Console> Console, const std::vector
INFO_MESSAGE("[SOH] NoZ " + std::string(state ? "enabled" : "disabled")); INFO_MESSAGE("[SOH] NoZ " + std::string(state ? "enabled" : "disabled"));
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not " + INFO_MESSAGE("[SOH] Command failed: Could not " + std::string(state ? "enable" : "disable") + " NoZ.");
std::string(state ? "enable" : "disable") + " NoZ.");
return 1; return 1;
} }
} }
static bool OneHitKOHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool OneHitKOHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -941,13 +979,13 @@ static bool OneHitKOHandler(std::shared_ptr<Ship::Console> Console, const std::v
INFO_MESSAGE("[SOH] One-hit KO " + std::string(state ? "enabled" : "disabled")); INFO_MESSAGE("[SOH] One-hit KO " + std::string(state ? "enabled" : "disabled"));
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not " + INFO_MESSAGE("[SOH] Command failed: Could not " + std::string(state ? "enable" : "disable") + " One-hit KO.");
std::string(state ? "enable" : "disable") + " One-hit KO.");
return 1; return 1;
} }
} }
static bool PacifistHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool PacifistHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -969,13 +1007,13 @@ static bool PacifistHandler(std::shared_ptr<Ship::Console> Console, const std::v
INFO_MESSAGE("[SOH] Pacifist " + std::string(state ? "enabled" : "disabled")); INFO_MESSAGE("[SOH] Pacifist " + std::string(state ? "enabled" : "disabled"));
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not " + INFO_MESSAGE("[SOH] Command failed: Could not " + std::string(state ? "enable" : "disable") + " Pacifist.");
std::string(state ? "enable" : "disable") + " Pacifist.");
return 1; return 1;
} }
} }
static bool PaperLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool PaperLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -998,13 +1036,13 @@ static bool PaperLinkHandler(std::shared_ptr<Ship::Console> Console, const std::
INFO_MESSAGE("[SOH] Paper Link " + std::string(state ? "enabled" : "disabled")); INFO_MESSAGE("[SOH] Paper Link " + std::string(state ? "enabled" : "disabled"));
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not " + INFO_MESSAGE("[SOH] Command failed: Could not " + std::string(state ? "enable" : "disable") + " Paper Link.");
std::string(state ? "enable" : "disable") + " Paper Link.");
return 1; return 1;
} }
} }
static bool RainstormHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool RainstormHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -1026,13 +1064,13 @@ static bool RainstormHandler(std::shared_ptr<Ship::Console> Console, const std::
INFO_MESSAGE("[SOH] Rainstorm " + std::string(state ? "enabled" : "disabled")); INFO_MESSAGE("[SOH] Rainstorm " + std::string(state ? "enabled" : "disabled"));
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not " + INFO_MESSAGE("[SOH] Command failed: Could not " + std::string(state ? "enable" : "disable") + " Rainstorm.");
std::string(state ? "enable" : "disable") + " Rainstorm.");
return 1; return 1;
} }
} }
static bool ReverseControlsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool ReverseControlsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -1051,17 +1089,17 @@ static bool ReverseControlsHandler(std::shared_ptr<Ship::Console> Console, const
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect); state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
if (result == GameInteractionEffectQueryResult::Possible) { if (result == GameInteractionEffectQueryResult::Possible) {
INFO_MESSAGE("[SOH] Reverse controls " + INFO_MESSAGE("[SOH] Reverse controls " + std::string(state ? "enabled" : "disabled"));
std::string(state ? "enabled" : "disabled"));
return 0; return 0;
} else { } else {
INFO_MESSAGE("[SOH] Command failed: Could not " + INFO_MESSAGE("[SOH] Command failed: Could not " + std::string(state ? "enable" : "disable") +
std::string(state ? "enable" : "disable") + " Reverse controls."); " Reverse controls.");
return 1; return 1;
} }
} }
static bool UpdateRupeesHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool UpdateRupeesHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -1085,7 +1123,8 @@ static bool UpdateRupeesHandler(std::shared_ptr<Ship::Console> Console, const st
} }
} }
static bool SpeedModifierHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool SpeedModifierHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -1115,7 +1154,8 @@ const static std::map<std::string, uint16_t> boots {
{ "hover", EQUIP_VALUE_BOOTS_HOVER }, { "hover", EQUIP_VALUE_BOOTS_HOVER },
}; };
static bool BootsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool BootsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -1146,7 +1186,8 @@ const static std::map<std::string, uint16_t> shields {
{ "mirror", ITEM_SHIELD_MIRROR }, { "mirror", ITEM_SHIELD_MIRROR },
}; };
static bool GiveShieldHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool GiveShieldHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -1171,7 +1212,8 @@ static bool GiveShieldHandler(std::shared_ptr<Ship::Console> Console, const std:
} }
} }
static bool TakeShieldHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool TakeShieldHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -1196,7 +1238,8 @@ static bool TakeShieldHandler(std::shared_ptr<Ship::Console> Console, const std:
} }
} }
static bool KnockbackHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool KnockbackHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -1226,7 +1269,8 @@ static bool KnockbackHandler(std::shared_ptr<Ship::Console> Console, const std::
} }
} }
static bool ElectrocuteHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool ElectrocuteHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
GameInteractionEffectBase* effect = new GameInteractionEffect::ElectrocutePlayer(); GameInteractionEffectBase* effect = new GameInteractionEffect::ElectrocutePlayer();
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
@ -1239,7 +1283,8 @@ static bool ElectrocuteHandler(std::shared_ptr<Ship::Console> Console, const std
} }
} }
static bool BurnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool BurnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
GameInteractionEffectBase* effect = new GameInteractionEffect::BurnPlayer(); GameInteractionEffectBase* effect = new GameInteractionEffect::BurnPlayer();
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect); GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
@ -1252,7 +1297,8 @@ static bool BurnHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
} }
} }
static bool CuccoStormHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool CuccoStormHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
GameInteractionEffectQueryResult result = GameInteractor::RawAction::SpawnActor(ACTOR_EN_NIW, 0); GameInteractionEffectQueryResult result = GameInteractor::RawAction::SpawnActor(ACTOR_EN_NIW, 0);
if (result == GameInteractionEffectQueryResult::Possible) { if (result == GameInteractionEffectQueryResult::Possible) {
@ -1264,7 +1310,8 @@ static bool CuccoStormHandler(std::shared_ptr<Ship::Console> Console, const std:
} }
} }
static bool GenerateRandoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool GenerateRandoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() == 1) { if (args.size() == 1) {
if (GenerateRandomizer()) { if (GenerateRandomizer()) {
return 0; return 0;
@ -1287,7 +1334,6 @@ static bool GenerateRandoHandler(std::shared_ptr<Ship::Console> Console, const s
return 1; return 1;
} }
ERROR_MESSAGE("[SOH] Rando generation already in progress"); ERROR_MESSAGE("[SOH] Rando generation already in progress");
return 1; return 1;
} }
@ -1316,7 +1362,8 @@ static constexpr std::array<std::pair<const char*, CosmeticGroup>, COSMETICS_GRO
{ "message", COSMETICS_GROUP_MESSAGE }, { "message", COSMETICS_GROUP_MESSAGE },
} }; } };
static bool CosmeticsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool CosmeticsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -1357,18 +1404,13 @@ static bool CosmeticsHandler(std::shared_ptr<Ship::Console> Console, const std::
} }
static std::map<std::string, SeqType> sfx_groups = { static std::map<std::string, SeqType> sfx_groups = {
{"bgm", SEQ_BGM_WORLD}, { "bgm", SEQ_BGM_WORLD }, { "fanfares", SEQ_FANFARE }, { "events", SEQ_BGM_EVENT },
{"fanfares", SEQ_FANFARE}, { "battle", SEQ_BGM_BATTLE }, { "ocarina", SEQ_OCARINA }, { "instruments", SEQ_INSTRUMENT },
{"events", SEQ_BGM_EVENT}, { "sfx", SEQ_SFX }, { "voices", SEQ_VOICE }, { "custom", SEQ_BGM_CUSTOM },
{"battle", SEQ_BGM_BATTLE},
{"ocarina", SEQ_OCARINA},
{"instruments", SEQ_INSTRUMENT},
{"sfx", SEQ_SFX},
{"voices", SEQ_VOICE},
{"custom", SEQ_BGM_CUSTOM},
}; };
static bool SfxHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { static bool SfxHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args,
std::string* output) {
if (args.size() < 2) { if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed"); ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1; return 1;
@ -1417,17 +1459,23 @@ void DebugConsole_Init(void) {
// Save States // Save States
CMD_REGISTER("save_state", { SaveStateHandler, "Save a state." }); CMD_REGISTER("save_state", { SaveStateHandler, "Save a state." });
CMD_REGISTER("load_state", { LoadStateHandler, "Load a state." }); CMD_REGISTER("load_state", { LoadStateHandler, "Load a state." });
CMD_REGISTER("set_slot", {StateSlotSelectHandler, "Selects a SaveState slot", { CMD_REGISTER("set_slot", { StateSlotSelectHandler,
"Selects a SaveState slot",
{
{ "Slot number", Ship::ArgumentType::NUMBER }, { "Slot number", Ship::ArgumentType::NUMBER },
} }); } });
// Map & Location // Map & Location
CMD_REGISTER("void", { VoidHandler, "Voids out of the current map." }); CMD_REGISTER("void", { VoidHandler, "Voids out of the current map." });
CMD_REGISTER("reload", { ReloadHandler, "Reloads the current map." }); CMD_REGISTER("reload", { ReloadHandler, "Reloads the current map." });
CMD_REGISTER("fw", {FWHandler, "Spawns the player where Farore's Wind is set.", { CMD_REGISTER("fw", { FWHandler,
"Spawns the player where Farore's Wind is set.",
{
{ "clear|warp|backup", Ship::ArgumentType::TEXT }, { "clear|warp|backup", Ship::ArgumentType::TEXT },
} }); } });
CMD_REGISTER("entrance", {EntranceHandler, "Sends player to the entered entrance (hex)", { CMD_REGISTER("entrance", { EntranceHandler,
"Sends player to the entered entrance (hex)",
{
{ "entrance", Ship::ArgumentType::NUMBER }, { "entrance", Ship::ArgumentType::NUMBER },
} }); } });
@ -1436,15 +1484,23 @@ void DebugConsole_Init(void) {
CMD_REGISTER("map", { LoadSceneHandler, "Load up kak?" }); CMD_REGISTER("map", { LoadSceneHandler, "Load up kak?" });
CMD_REGISTER("rupee", {RupeeHandler, "Set your rupee counter.", { CMD_REGISTER("rupee", { RupeeHandler,
"Set your rupee counter.",
{
{ "amount", Ship::ArgumentType::NUMBER }, { "amount", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("bItem", {BHandler, "Set an item to the B button.", { CMD_REGISTER("bItem", { BHandler,
"Set an item to the B button.",
{
{ "Item ID", Ship::ArgumentType::NUMBER }, { "Item ID", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("spawn", { ActorSpawnHandler, "Spawn an actor.", { { "actor name/id", Ship::ArgumentType::NUMBER }, // TODO there should be an actor_id arg type CMD_REGISTER("spawn",
{ ActorSpawnHandler,
"Spawn an actor.",
{
{ "actor name/id", Ship::ArgumentType::NUMBER }, // TODO there should be an actor_id arg type
{ "data", Ship::ArgumentType::NUMBER }, { "data", Ship::ArgumentType::NUMBER },
{ "x", Ship::ArgumentType::NUMBER, true }, { "x", Ship::ArgumentType::NUMBER, true },
{ "y", Ship::ArgumentType::NUMBER, true }, { "y", Ship::ArgumentType::NUMBER, true },
@ -1454,46 +1510,64 @@ void DebugConsole_Init(void) {
{ "rz", Ship::ArgumentType::NUMBER, true }, { "rz", Ship::ArgumentType::NUMBER, true },
} }); } });
CMD_REGISTER("pos", {SetPosHandler, "Sets the position of the player.", { CMD_REGISTER("pos", { SetPosHandler,
"Sets the position of the player.",
{
{ "x", Ship::ArgumentType::NUMBER, true }, { "x", Ship::ArgumentType::NUMBER, true },
{ "y", Ship::ArgumentType::NUMBER, true }, { "y", Ship::ArgumentType::NUMBER, true },
{ "z", Ship::ArgumentType::NUMBER, true }, { "z", Ship::ArgumentType::NUMBER, true },
} }); } });
CMD_REGISTER("addammo", {AddAmmoHandler, "Adds ammo of an item.", { CMD_REGISTER("addammo", { AddAmmoHandler,
"Adds ammo of an item.",
{
{ "sticks|nuts|bombs|seeds|arrows|bombchus|beans", Ship::ArgumentType::TEXT }, { "sticks|nuts|bombs|seeds|arrows|bombchus|beans", Ship::ArgumentType::TEXT },
{ "count", Ship::ArgumentType::NUMBER }, { "count", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("takeammo", {TakeAmmoHandler, "Removes ammo of an item.", { CMD_REGISTER("takeammo", { TakeAmmoHandler,
"Removes ammo of an item.",
{
{ "sticks|nuts|bombs|seeds|arrows|bombchus|beans", Ship::ArgumentType::TEXT }, { "sticks|nuts|bombs|seeds|arrows|bombchus|beans", Ship::ArgumentType::TEXT },
{ "count", Ship::ArgumentType::NUMBER }, { "count", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("bottle", {BottleHandler, "Changes item in a bottle slot.", { CMD_REGISTER("bottle", { BottleHandler,
"Changes item in a bottle slot.",
{
{ "item", Ship::ArgumentType::TEXT }, { "item", Ship::ArgumentType::TEXT },
{ "slot", Ship::ArgumentType::NUMBER }, { "slot", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("give_item", {GiveItemHandler, "Gives an item to the player as if it was given from an actor", { CMD_REGISTER("give_item", { GiveItemHandler,
"Gives an item to the player as if it was given from an actor",
{
{ "vanilla|randomizer", Ship::ArgumentType::TEXT }, { "vanilla|randomizer", Ship::ArgumentType::TEXT },
{ "giveItemID", Ship::ArgumentType::NUMBER }, { "giveItemID", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("item", {ItemHandler, "Sets item ID in arg 1 into slot arg 2. No boundary checks. Use with caution.", { CMD_REGISTER("item", { ItemHandler,
"Sets item ID in arg 1 into slot arg 2. No boundary checks. Use with caution.",
{
{ "slot", Ship::ArgumentType::NUMBER }, { "slot", Ship::ArgumentType::NUMBER },
{ "item id", Ship::ArgumentType::NUMBER }, { "item id", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("invisible", {InvisibleHandler, "Activate Link's Elvish cloak, making him appear invisible.", { CMD_REGISTER("invisible", { InvisibleHandler,
"Activate Link's Elvish cloak, making him appear invisible.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("giant_link", {GiantLinkHandler, "Turn Link into a giant Lonky boi.", { CMD_REGISTER("giant_link", { GiantLinkHandler,
"Turn Link into a giant Lonky boi.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("minish_link", {MinishLinkHandler, "Turn Link into a minish boi.", { CMD_REGISTER("minish_link", { MinishLinkHandler,
"Turn Link into a minish boi.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
@ -1503,25 +1577,35 @@ void DebugConsole_Init(void) {
CMD_REGISTER("remove_heart_container", CMD_REGISTER("remove_heart_container",
{ RemoveHeartContainerHandler, "Remove a heart from Link. The minimal amount of hearts is 3." }); { RemoveHeartContainerHandler, "Remove a heart from Link. The minimal amount of hearts is 3." });
CMD_REGISTER("gravity", {GravityHandler, "Set gravity level.", { CMD_REGISTER("gravity", { GravityHandler,
"Set gravity level.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("no_ui", {NoUIHandler, "Disables the UI.", { CMD_REGISTER("no_ui", { NoUIHandler,
"Disables the UI.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("freeze", { FreezeHandler, "Freezes Link in place" }); CMD_REGISTER("freeze", { FreezeHandler, "Freezes Link in place" });
CMD_REGISTER("defense_modifier", {DefenseModifierHandler, "Sets the defense modifier.", { CMD_REGISTER("defense_modifier", { DefenseModifierHandler,
"Sets the defense modifier.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("damage", {DamageHandler, "Deal damage to Link.", { CMD_REGISTER("damage", { DamageHandler,
"Deal damage to Link.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("heal", {HealHandler, "Heals Link.", { CMD_REGISTER("heal", { HealHandler,
"Heals Link.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
@ -1529,50 +1613,71 @@ void DebugConsole_Init(void) {
CMD_REGISTER("empty_magic", { EmptyMagicHandler, "Empties magic." }); CMD_REGISTER("empty_magic", { EmptyMagicHandler, "Empties magic." });
CMD_REGISTER("no_z", {NoZHandler, "Disables Z-button presses.", { CMD_REGISTER("no_z", { NoZHandler,
"Disables Z-button presses.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("ohko", { OneHitKOHandler, CMD_REGISTER("ohko", { OneHitKOHandler,
"Activates one hit KO. Any damage kills Link and he cannot gain health in this mode.", { "Activates one hit KO. Any damage kills Link and he cannot gain health in this mode.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("pacifist", {PacifistHandler, "Activates pacifist mode. Prevents Link from using his weapon.", { CMD_REGISTER("pacifist", { PacifistHandler,
"Activates pacifist mode. Prevents Link from using his weapon.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("paper_link", {PaperLinkHandler, "Link but made out of paper.", { CMD_REGISTER("paper_link", { PaperLinkHandler,
"Link but made out of paper.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("rainstorm", { RainstormHandler, "Activates rainstorm." }); CMD_REGISTER("rainstorm", { RainstormHandler, "Activates rainstorm." });
CMD_REGISTER("reverse_controls", {ReverseControlsHandler, "Reverses the controls.", { CMD_REGISTER("reverse_controls", { ReverseControlsHandler,
"Reverses the controls.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("update_rupees", {UpdateRupeesHandler, "Adds rupees.", { CMD_REGISTER("update_rupees", { UpdateRupeesHandler,
"Adds rupees.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("speed_modifier", {SpeedModifierHandler, "Sets the speed modifier.", { CMD_REGISTER("speed_modifier", { SpeedModifierHandler,
"Sets the speed modifier.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
CMD_REGISTER("boots", {BootsHandler, "Activates boots.", { CMD_REGISTER("boots", { BootsHandler,
"Activates boots.",
{
{ "kokiri|iron|hover", Ship::ArgumentType::TEXT }, { "kokiri|iron|hover", Ship::ArgumentType::TEXT },
} }); } });
CMD_REGISTER("giveshield", {GiveShieldHandler, "Gives a shield and equips it when Link is the right age for it.", { CMD_REGISTER("giveshield", { GiveShieldHandler,
"Gives a shield and equips it when Link is the right age for it.",
{
{ "deku|hylian|mirror", Ship::ArgumentType::TEXT }, { "deku|hylian|mirror", Ship::ArgumentType::TEXT },
} }); } });
CMD_REGISTER("takeshield", {TakeShieldHandler, "Takes a shield and unequips it if Link is wearing it.", { CMD_REGISTER("takeshield", { TakeShieldHandler,
"Takes a shield and unequips it if Link is wearing it.",
{
{ "deku|hylian|mirror", Ship::ArgumentType::TEXT }, { "deku|hylian|mirror", Ship::ArgumentType::TEXT },
} }); } });
CMD_REGISTER("knockback", {KnockbackHandler, "Knocks Link back.", { CMD_REGISTER("knockback", { KnockbackHandler,
"Knocks Link back.",
{
{ "value", Ship::ArgumentType::NUMBER }, { "value", Ship::ArgumentType::NUMBER },
} }); } });
@ -1582,17 +1687,23 @@ void DebugConsole_Init(void) {
CMD_REGISTER("cucco_storm", { CuccoStormHandler, "Cucco Storm" }); CMD_REGISTER("cucco_storm", { CuccoStormHandler, "Cucco Storm" });
CMD_REGISTER("gen_rando", {GenerateRandoHandler, "Generate a randomizer seed", { CMD_REGISTER("gen_rando", { GenerateRandoHandler,
"Generate a randomizer seed",
{
{ "seed|count", Ship::ArgumentType::NUMBER, true }, { "seed|count", Ship::ArgumentType::NUMBER, true },
{ "testing", Ship::ArgumentType::NUMBER, true }, { "testing", Ship::ArgumentType::NUMBER, true },
} }); } });
CMD_REGISTER("cosmetics", {CosmeticsHandler, "Change cosmetics.", { CMD_REGISTER("cosmetics", { CosmeticsHandler,
"Change cosmetics.",
{
{ "reset|randomize", Ship::ArgumentType::TEXT }, { "reset|randomize", Ship::ArgumentType::TEXT },
{ "group name", Ship::ArgumentType::TEXT, true }, { "group name", Ship::ArgumentType::TEXT, true },
} }); } });
CMD_REGISTER("sfx", {SfxHandler, "Change SFX.", { CMD_REGISTER("sfx", { SfxHandler,
"Change SFX.",
{
{ "reset|randomize", Ship::ArgumentType::TEXT }, { "reset|randomize", Ship::ArgumentType::TEXT },
{ "group_name", Ship::ArgumentType::TEXT, true }, { "group_name", Ship::ArgumentType::TEXT, true },
} }); } });

View file

@ -29,7 +29,8 @@ void MessageViewer::DrawElement() {
ImGui::Text("Table ID"); ImGui::Text("Table ID");
ImGui::SameLine(); ImGui::SameLine();
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::InputText("##TableID", mTableIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum); ImGui::InputText("##TableID", mTableIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter,
UIWidgets::TextFilters::FilterAlphaNum);
UIWidgets::InsertHelpHoverText("Leave blank for vanilla table"); UIWidgets::InsertHelpHoverText("Leave blank for vanilla table");
ImGui::Text("Text ID"); ImGui::Text("Text ID");
ImGui::SameLine(); ImGui::SameLine();
@ -41,7 +42,8 @@ void MessageViewer::DrawElement() {
case HEXADECIMAL: case HEXADECIMAL:
default: default:
ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsHexadecimal); ImGui::InputText("##TextID", mTextIdBuf, MAX_STRING_SIZE, ImGuiInputTextFlags_CharsHexadecimal);
UIWidgets::InsertHelpHoverText("Hexadecimal Text ID of the message to load. Hexadecimal digits only (0-9/A-F)."); UIWidgets::InsertHelpHoverText(
"Hexadecimal Text ID of the message to load. Hexadecimal digits only (0-9/A-F).");
break; break;
} }
PopStyleInput(); PopStyleInput();
@ -169,8 +171,7 @@ void FindMessage(PlayState* play, const uint16_t textId, const uint8_t language)
font->msgLength = nextSeg - foundSeg; font->msgLength = nextSeg - foundSeg;
} }
static const char* msgStaticTbl[] = static const char* msgStaticTbl[] = {
{
gDefaultMessageBackgroundTex, gDefaultMessageBackgroundTex,
gSignMessageBackgroundTex, gSignMessageBackgroundTex,
gNoteStaffMessageBackgroundTex, gNoteStaffMessageBackgroundTex,
@ -207,7 +208,8 @@ void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t lan
const CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(tableId, textId); const CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(tableId, textId);
font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition(); font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition();
switch (language) { switch (language) {
font->msgLength = SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetForLanguage(language), maxBufferSize); font->msgLength =
SohUtils::CopyStringToCharBuffer(buffer, messageEntry.GetForLanguage(language), maxBufferSize);
} }
msgCtx->msgLength = static_cast<int32_t>(font->msgLength); msgCtx->msgLength = static_cast<int32_t>(font->msgLength);
} }
@ -261,5 +263,3 @@ void MessageDebug_DisplayCustomMessage(const char* customMessage) {
CustomMessage(customMessage, customMessage, customMessage)); CustomMessage(customMessage, customMessage, customMessage));
MessageDebug_StartTextBox(MessageViewer::TABLE_ID, 0, 0); MessageDebug_StartTextBox(MessageViewer::TABLE_ID, 0, 0);
} }

View file

@ -25,7 +25,6 @@ void MessageDebug_DisplayCustomMessage(const char* customMessage);
#ifdef __cplusplus #ifdef __cplusplus
} }
class MessageViewer : public Ship::GuiWindow { class MessageViewer : public Ship::GuiWindow {
public: public:
static inline const char* TABLE_ID = "MessageViewer"; static inline const char* TABLE_ID = "MessageViewer";
@ -57,6 +56,5 @@ private:
bool mDisplayCustomMessageClicked = false; bool mDisplayCustomMessageClicked = false;
}; };
#endif //__cplusplus #endif //__cplusplus
#endif // CUSTOMMESSAGEDEBUGGER_H #endif // CUSTOMMESSAGEDEBUGGER_H

View file

@ -46,18 +46,12 @@ typedef enum {
} RetrievalMethod; } RetrievalMethod;
std::array<const char*, 12> acMapping = { std::array<const char*, 12> acMapping = {
"Switch", "Switch", "Background (Prop type 1)",
"Background (Prop type 1)", "Player", "Bomb",
"Player", "NPC", "Enemy",
"Bomb", "Prop type 2", "Item/Action",
"NPC", "Misc.", "Boss",
"Enemy", "Door", "Chest",
"Prop type 2",
"Item/Action",
"Misc.",
"Boss",
"Door",
"Chest",
}; };
using namespace UIWidgets; using namespace UIWidgets;
@ -76,7 +70,8 @@ const std::string GetActorDescription(u16 id) {
template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) { template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) {
// First group encapsulates the inner portion and border // First group encapsulates the inner portion and border
ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0), ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0),
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY); ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeX |
ImGuiChildFlags_AutoResizeY);
// Second group encapsulates just the inner portion // Second group encapsulates just the inner portion
ImGui::BeginGroup(); ImGui::BeginGroup();
@ -376,33 +371,11 @@ void CreateActorSpecificData() {
} }
static const char* items[] = { static const char* items[] = {
"Green Rupee", "Green Rupee", "Blue Rupee", "Red Rupee", "Recovery Heart", "Bombs (A)", "Arrow",
"Blue Rupee", "Heart Piece", "Heart Container", "Arrows (5)", "Arrows (10)", "Arrows (30)", "Bombs (B)",
"Red Rupee", "Deku Nuts (5)", "Deku Stick", "Magic (Large)", "Magic (Small)", "Deku Seeds (5)", "Small Key",
"Recovery Heart", "Flexible", "Gold Rupee", "Purple Rupee", "Deku Shield", "Hylian Shield", "Zora Tunic",
"Bombs (A)", "Goron Tunic", "Bombs (Special)", "Bombchus",
"Arrow",
"Heart Piece",
"Heart Container",
"Arrows (5)",
"Arrows (10)",
"Arrows (30)",
"Bombs (B)",
"Deku Nuts (5)",
"Deku Stick",
"Magic (Large)",
"Magic (Small)",
"Deku Seeds (5)",
"Small Key",
"Flexible",
"Gold Rupee",
"Purple Rupee",
"Deku Shield",
"Hylian Shield",
"Zora Tunic",
"Goron Tunic",
"Bombs (Special)",
"Bombchus",
}; };
int selectedItem = params & 0xFF; int selectedItem = params & 0xFF;
@ -413,33 +386,11 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_OBJ_COMB] = [](s16 params) -> s16 { actorSpecificData[ACTOR_OBJ_COMB] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = {
"Green Rupee", "Green Rupee", "Blue Rupee", "Red Rupee", "Recovery Heart", "Bombs (A)", "Arrow",
"Blue Rupee", "Heart Piece", "Heart Container", "Arrows (5)", "Arrows (10)", "Arrows (30)", "Bombs (B)",
"Red Rupee", "Deku Nuts (5)", "Deku Stick", "Magic (Large)", "Magic (Small)", "Deku Seeds (5)", "Small Key",
"Recovery Heart", "Flexible", "Gold Rupee", "Purple Rupee", "Deku Shield", "Hylian Shield", "Zora Tunic",
"Bombs (A)", "Goron Tunic", "Bombs (Special)", "Bombchus",
"Arrow",
"Heart Piece",
"Heart Container",
"Arrows (5)",
"Arrows (10)",
"Arrows (30)",
"Bombs (B)",
"Deku Nuts (5)",
"Deku Stick",
"Magic (Large)",
"Magic (Small)",
"Deku Seeds (5)",
"Small Key",
"Flexible",
"Gold Rupee",
"Purple Rupee",
"Deku Shield",
"Hylian Shield",
"Zora Tunic",
"Goron Tunic",
"Bombs (Special)",
"Bombchus",
}; };
int selectedItem = params & 0xFF; int selectedItem = params & 0xFF;
@ -580,14 +531,7 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_EN_ELF] = [](s16 params) -> s16 { actorSpecificData[ACTOR_EN_ELF] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = {
"Navi", "Navi", "Revive Bottle", "Heal Timed", "Kokiri", "Spawner", "Revive Death", "Heal", "Heal Big",
"Revive Bottle",
"Heal Timed",
"Kokiri",
"Spawner",
"Revive Death",
"Heal",
"Heal Big",
}; };
int selectedItem = params; int selectedItem = params;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
@ -636,18 +580,14 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_DOOR_WARP1] = [](s16 params) -> s16 { actorSpecificData[ACTOR_DOOR_WARP1] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = {
"Blue Crystal", // -2 "Blue Crystal", // -2
"Dungeon Adult", "Dungeon Adult", "Dungeon Child",
"Dungeon Child",
"Clear Flag", // Activate on temp clear flag "Clear Flag", // Activate on temp clear flag
"Sages", // Used by sages warping into chamber of sages during their cutscene "Sages", // Used by sages warping into chamber of sages during their cutscene
"Purple Crystal", "Purple Crystal",
"Yellow", // The colored variants don't warp, they are cutscene setpieces "Yellow", // The colored variants don't warp, they are cutscene setpieces
"Blue Ruto", "Blue Ruto",
"Destination", // Spawning in after having taken a warp "Destination", // Spawning in after having taken a warp
"UNK 7", "UNK 7", "Orange", "Green", "Red",
"Orange",
"Green",
"Red",
}; };
int selectedItem = params + 2; int selectedItem = params + 2;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
@ -819,11 +759,7 @@ void CreateActorSpecificData() {
}; };
actorSpecificData[ACTOR_EN_KUSA] = [](s16 params) -> s16 { actorSpecificData[ACTOR_EN_KUSA] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = { "0", "1", "2" };
"0",
"1",
"2"
};
int type = params & 3; int type = params & 3;
ImGui::Combo("Type", &type, items, IM_ARRAYSIZE(items)); ImGui::Combo("Type", &type, items, IM_ARRAYSIZE(items));
@ -845,12 +781,7 @@ void CreateActorSpecificData() {
}; };
actorSpecificData[ActorDB::Instance->RetrieveId("En_Partner")] = [](s16 params) -> s16 { actorSpecificData[ActorDB::Instance->RetrieveId("En_Partner")] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = { "Port 1", "Port 2", "Port 3", "Port 4" };
"Port 1",
"Port 2",
"Port 3",
"Port 4"
};
int selectedItem = params; int selectedItem = params;
if (ImGui::Combo("Controller Port", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Controller Port", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem; return selectedItem;
@ -986,17 +917,20 @@ void ActorViewerWindow::DrawElement() {
PushStyleHeader(THEME_COLOR); PushStyleHeader(THEME_COLOR);
if (ImGui::TreeNode("Selected Actor")) { if (ImGui::TreeNode("Selected Actor")) {
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str()); ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str());
ImGui::Text("Description: %s", GetActorDescription(display->id).c_str()); ImGui::Text("Description: %s", GetActorDescription(display->id).c_str());
ImGui::Text("Category: %s", acMapping[display->category]); ImGui::Text("Category: %s", acMapping[display->category]);
ImGui::Text("ID: %d", display->id); ImGui::Text("ID: %d", display->id);
ImGui::Text("Parameters: %d", display->params); ImGui::Text("Parameters: %d", display->params);
}, "Selected Actor"); },
"Selected Actor");
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::Text("Actor Position"); ImGui::Text("Actor Position");
@ -1005,9 +939,11 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("Z##CurPos", ImGuiDataType_Float, &display->world.pos.z); ImGui::InputScalar("Z##CurPos", ImGuiDataType_Float, &display->world.pos.z);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
PopStyleInput(); PopStyleInput();
}, "Actor Position"); },
"Actor Position");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::Text("Actor Rotation"); ImGui::Text("Actor Rotation");
@ -1016,7 +952,8 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("Z##CurRot", ImGuiDataType_S16, &display->world.rot.z); ImGui::InputScalar("Z##CurRot", ImGuiDataType_S16, &display->world.rot.z);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
PopStyleInput(); PopStyleInput();
}, "Actor Rotation"); },
"Actor Rotation");
if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) { if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) {
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
@ -1025,17 +962,21 @@ void ActorViewerWindow::DrawElement() {
UIWidgets::InsertHelpHoverText("Some actors might not use this!"); UIWidgets::InsertHelpHoverText("Some actors might not use this!");
} }
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("flags"); ImGui::Text("flags");
UIWidgets::DrawFlagArray32("flags", display->flags); UIWidgets::DrawFlagArray32("flags", display->flags);
}, "flags"); },
"flags");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("bgCheckFlags"); ImGui::Text("bgCheckFlags");
UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags); UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags);
}, "bgCheckFlags"); },
"bgCheckFlags");
if (Button("Refresh", ButtonOptions().Color(THEME_COLOR))) { if (Button("Refresh", ButtonOptions().Color(THEME_COLOR))) {
PopulateActorDropdown(category, list); PopulateActorDropdown(category, list);
@ -1059,7 +1000,10 @@ void ActorViewerWindow::DrawElement() {
Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos); Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos);
} }
if (Button("Fetch from Target", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor with target arrow above it. You might need C-Up for enemies"))) { if (Button("Fetch from Target",
ButtonOptions()
.Color(THEME_COLOR)
.Tooltip("Grabs actor with target arrow above it. You might need C-Up for enemies"))) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
fetch = player->talkActor; fetch = player->talkActor;
if (fetch != NULL) { if (fetch != NULL) {
@ -1069,7 +1013,8 @@ void ActorViewerWindow::DrawElement() {
rm = TARGET; rm = TARGET;
} }
} }
if (Button("Fetch from Held", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor that Link is holding"))) { if (Button("Fetch from Held",
ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor that Link is holding"))) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
fetch = player->heldActor; fetch = player->heldActor;
if (fetch != NULL) { if (fetch != NULL) {
@ -1079,7 +1024,8 @@ void ActorViewerWindow::DrawElement() {
rm = HELD; rm = HELD;
} }
} }
if (Button("Fetch from Interaction", ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor from \"interaction range\""))) { if (Button("Fetch from Interaction",
ButtonOptions().Color(THEME_COLOR).Tooltip("Grabs actor from \"interaction range\""))) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
fetch = player->interactRangeActor; fetch = player->interactRangeActor;
if (fetch != NULL) { if (fetch != NULL) {
@ -1102,14 +1048,14 @@ void ActorViewerWindow::DrawElement() {
} }
if (!SohUtils::IsStringEmpty(searchString) && !actors.empty()) { if (!SohUtils::IsStringEmpty(searchString) && !actors.empty()) {
std::string preview = currentSelectedInDropdown == -1 ? "Please Select" : ActorDB::Instance->RetrieveEntry(actors[currentSelectedInDropdown]).desc; std::string preview = currentSelectedInDropdown == -1
? "Please Select"
: ActorDB::Instance->RetrieveEntry(actors[currentSelectedInDropdown]).desc;
PushStyleCombobox(THEME_COLOR); PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("Results", preview.c_str())) { if (ImGui::BeginCombo("Results", preview.c_str())) {
for (u8 i = 0; i < actors.size(); i++) { for (u8 i = 0; i < actors.size(); i++) {
if (ImGui::Selectable( if (ImGui::Selectable(ActorDB::Instance->RetrieveEntry(actors[i]).desc.c_str(),
ActorDB::Instance->RetrieveEntry(actors[i]).desc.c_str(), i == currentSelectedInDropdown)) {
i == currentSelectedInDropdown
)) {
currentSelectedInDropdown = i; currentSelectedInDropdown = i;
newActor.id = actors[i]; newActor.id = actors[i];
} }
@ -1124,7 +1070,8 @@ void ActorViewerWindow::DrawElement() {
newActor.params = 0; newActor.params = 0;
} }
CVarCheckbox("Advanced mode", CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), CheckboxOptions().Tooltip("Changes the actor specific param menus with a direct input")); CVarCheckbox("Advanced mode", CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"),
CheckboxOptions().Tooltip("Changes the actor specific param menus with a direct input"));
if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), 0)) { if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ActorViewer.AdvancedParams"), 0)) {
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
@ -1137,16 +1084,19 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one); ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one);
PopStyleInput(); PopStyleInput();
} else { } else {
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Actor Specific Data"); ImGui::Text("Actor Specific Data");
newActor.params = actorSpecificData[newActor.id](newActor.params); newActor.params = actorSpecificData[newActor.id](newActor.params);
}, "Actor Specific Data"); },
"Actor Specific Data");
} }
} }
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::Text("New Actor Position"); ImGui::Text("New Actor Position");
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
@ -1155,9 +1105,11 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("Z##NewPos", ImGuiDataType_Float, &newActor.pos.z); ImGui::InputScalar("Z##NewPos", ImGuiDataType_Float, &newActor.pos.z);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
PopStyleInput(); PopStyleInput();
}, "New Actor Position"); },
"New Actor Position");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::Text("New Actor Rotation"); ImGui::Text("New Actor Rotation");
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
@ -1166,7 +1118,8 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("Z##NewRot", ImGuiDataType_S16, &newActor.rot.z); ImGui::InputScalar("Z##NewRot", ImGuiDataType_S16, &newActor.rot.z);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
PopStyleInput(); PopStyleInput();
}, "New Actor Rotation"); },
"New Actor Rotation");
if (Button("Fetch from Link", ButtonOptions().Color(THEME_COLOR))) { if (Button("Fetch from Link", ButtonOptions().Color(THEME_COLOR))) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
@ -1214,7 +1167,8 @@ void ActorViewerWindow::DrawElement() {
{ 3, "Both" }, { 3, "Both" },
}; };
if (CVarCombobox("Actor Name Tags", CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), nameTagOptions, if (CVarCombobox(
"Actor Name Tags", CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), nameTagOptions,
ComboboxOptions().Color(THEME_COLOR).Tooltip("Adds \"name tags\" above actors for identification"))) { ComboboxOptions().Color(THEME_COLOR).Tooltip("Adds \"name tags\" above actors for identification"))) {
NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG); NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG);
ActorViewer_AddTagForAllActors(); ActorViewer_AddTagForAllActors();

View file

@ -68,9 +68,11 @@ void ColViewerWindow::DrawElement() {
CVarCombobox("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), ColRenderSettingNames, comboOpt); CVarCombobox("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), ColRenderSettingNames, comboOpt);
CVarCheckbox("Apply as decal", CVAR_DEVELOPER_TOOLS("ColViewer.Decal"), CVarCheckbox("Apply as decal", CVAR_DEVELOPER_TOOLS("ColViewer.Decal"),
checkOpt.DefaultValue(true).Tooltip("Applies the collision as a decal display. This can be useful if there is z-fighting occuring " checkOpt.DefaultValue(true).Tooltip(
"Applies the collision as a decal display. This can be useful if there is z-fighting occuring "
"with the scene geometry, but can cause other artifacts.")); "with the scene geometry, but can cause other artifacts."));
CVarCheckbox("Shaded", CVAR_DEVELOPER_TOOLS("ColViewer.Shaded"), checkOpt.DefaultValue(false).Tooltip("Applies the scene's shading to the collision display.")); CVarCheckbox("Shaded", CVAR_DEVELOPER_TOOLS("ColViewer.Shaded"),
checkOpt.DefaultValue(false).Tooltip("Applies the scene's shading to the collision display."));
// This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered() // This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered()
const std::string colorHelpText = "View and change the colors used for collision display."; const std::string colorHelpText = "View and change the colors used for collision display.";
@ -78,38 +80,58 @@ void ColViewerWindow::DrawElement() {
if (ImGui::TreeNode("Colors")) { if (ImGui::TreeNode("Colors")) {
UIWidgets::Tooltip(colorHelpText.c_str()); UIWidgets::Tooltip(colorHelpText.c_str());
if (CVarColorPicker("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }, false,
scene_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 })); ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
scene_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }));
} }
if (CVarColorPicker("Hookshot", CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Hookshot", CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }, false,
hookshot_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 })); ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
hookshot_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }));
} }
if (CVarColorPicker("Entrance", CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Entrance", CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }, false,
entrance_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 })); ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
entrance_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }));
} }
if (CVarColorPicker("Special Surface (Grass/Sand/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Special Surface (Grass/Sand/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"),
specialSurface_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 })); { 192, 255, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton,
THEME_COLOR)) {
specialSurface_col = VecFromRGBA8(
CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }));
} }
if (CVarColorPicker("Interactable (Vines/Crawlspace/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Interactable (Vines/Crawlspace/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"),
interactable_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 })); { 192, 0, 192, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton,
THEME_COLOR)) {
interactable_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 }));
} }
if (CVarColorPicker("Slope", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Slope", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }, false,
slope_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 })); ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
slope_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }));
} }
if (CVarColorPicker("Void", CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Void", CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
void_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 })); void_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid"), { 255, 0, 0, 255 }));
} }
if (CVarColorPicker("OC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("OC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
oc_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 })); oc_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorOC"), { 255, 255, 255, 255 }));
} }
if (CVarColorPicker("AC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("AC", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
ac_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 })); ac_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAC"), { 0, 0, 255, 255 }));
} }
if (CVarColorPicker("AT", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("AT", CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
at_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 })); at_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorAT"), { 255, 0, 0, 255 }));
} }
if (CVarColorPicker("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) { if (CVarColorPicker("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }, false,
waterbox_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 })); ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
waterbox_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }));
} }
ImGui::TreePop(); ImGui::TreePop();
@ -427,7 +449,8 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
// Draws the scene // Draws the scene
void DrawSceneCollision() { void DrawSceneCollision() {
ColRenderSetting showSceneColSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_DISABLED); ColRenderSetting showSceneColSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Scene"), COLVIEW_DISABLED);
if (showSceneColSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { if (showSceneColSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return; return;
@ -442,7 +465,8 @@ void DrawSceneCollision() {
// Draws all Bg Actors // Draws all Bg Actors
void DrawBgActorCollision() { void DrawBgActorCollision() {
ColRenderSetting showBgActorSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_DISABLED); ColRenderSetting showBgActorSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.BGActors"), COLVIEW_DISABLED);
if (showBgActorSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { if (showBgActorSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return; return;
} }
@ -567,7 +591,8 @@ void DrawColCheckList(std::vector<Gfx>& dl, Collider** objects, int32_t count) {
// Draws all Col Check objects // Draws all Col Check objects
void DrawColCheckCollision() { void DrawColCheckCollision() {
ColRenderSetting showColCheckSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), COLVIEW_DISABLED); ColRenderSetting showColCheckSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.ColCheck"), COLVIEW_DISABLED);
if (showColCheckSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { if (showColCheckSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return; return;
} }
@ -619,7 +644,8 @@ extern "C" f32 zdWaterBoxMinY;
// Draws all waterboxes // Draws all waterboxes
void DrawWaterboxList() { void DrawWaterboxList() {
ColRenderSetting showWaterboxSetting = (ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), COLVIEW_DISABLED); ColRenderSetting showWaterboxSetting =
(ColRenderSetting)CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), COLVIEW_DISABLED);
if (showWaterboxSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) { if (showWaterboxSetting == ColRenderDisabled || !CVarGetInteger(CVAR_DEVELOPER_TOOLS("ColViewer.Enabled"), 0)) {
return; return;
} }

View file

@ -2,11 +2,7 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
typedef enum { typedef enum { COLVIEW_DISABLED, COLVIEW_SOLID, COLVIEW_TRANSPARENT } ColViewerRenderSetting;
COLVIEW_DISABLED,
COLVIEW_SOLID,
COLVIEW_TRANSPARENT
} ColViewerRenderSetting;
#ifdef __cplusplus #ifdef __cplusplus
class ColViewerWindow : public Ship::GuiWindow { class ColViewerWindow : public Ship::GuiWindow {

View file

@ -74,11 +74,11 @@ u8 gAllAmmoItems[] = {
}; };
// Encapsulates what is drawn by the passed-in function within a border // Encapsulates what is drawn by the passed-in function within a border
template<typename T> template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) {
void DrawGroupWithBorder(T&& drawFunc, std::string section) {
// First group encapsulates the inner portion and border // First group encapsulates the inner portion and border
ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0), ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0),
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY); ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeX |
ImGuiChildFlags_AutoResizeY);
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
@ -104,14 +104,9 @@ char z2ASCII(int code) {
ret = code; ret = code;
} }
return char(ret); return char(ret);
} }
typedef enum MagicLevel { typedef enum MagicLevel { MAGIC_LEVEL_NONE, MAGIC_LEVEL_SINGLE, MAGIC_LEVEL_DOUBLE };
MAGIC_LEVEL_NONE,
MAGIC_LEVEL_SINGLE,
MAGIC_LEVEL_DOUBLE
};
std::unordered_map<int8_t, const char*> magicLevelMap = { std::unordered_map<int8_t, const char*> magicLevelMap = {
{ MAGIC_LEVEL_NONE, "None" }, { MAGIC_LEVEL_NONE, "None" },
@ -182,18 +177,22 @@ void DrawInfoTab() {
gSaveContext.health = gSaveContext.healthCapacity; // Clamp health to new max gSaveContext.health = gSaveContext.healthCapacity; // Clamp health to new max
} }
int32_t health = (int32_t)gSaveContext.health; int32_t health = (int32_t)gSaveContext.health;
if (SliderInt("Health", &health, intSliderOptionsBase.Tooltip("Current health. 16 units per full heart") if (SliderInt("Health", &health,
.Min(0).Max(gSaveContext.healthCapacity))) { intSliderOptionsBase.Tooltip("Current health. 16 units per full heart")
.Min(0)
.Max(gSaveContext.healthCapacity))) {
gSaveContext.health = (int16_t)health; gSaveContext.health = (int16_t)health;
} }
bool isDoubleDefenseAcquired = gSaveContext.isDoubleDefenseAcquired != 0; bool isDoubleDefenseAcquired = gSaveContext.isDoubleDefenseAcquired != 0;
if (Checkbox("Double Defense", &isDoubleDefenseAcquired, checkboxOptionsBase.Tooltip("Is double defense unlocked?"))) { if (Checkbox("Double Defense", &isDoubleDefenseAcquired,
checkboxOptionsBase.Tooltip("Is double defense unlocked?"))) {
gSaveContext.isDoubleDefenseAcquired = isDoubleDefenseAcquired; gSaveContext.isDoubleDefenseAcquired = isDoubleDefenseAcquired;
gSaveContext.inventory.defenseHearts = gSaveContext.inventory.defenseHearts =
gSaveContext.isDoubleDefenseAcquired ? 20 : 0; // Set to get the border drawn in the UI gSaveContext.isDoubleDefenseAcquired ? 20 : 0; // Set to get the border drawn in the UI
} }
if (Combobox("Magic Level", &gSaveContext.magicLevel, magicLevelMap, comboboxOptionsBase.Tooltip("Current magic level"))) { if (Combobox("Magic Level", &gSaveContext.magicLevel, magicLevelMap,
comboboxOptionsBase.Tooltip("Current magic level"))) {
gSaveContext.isMagicAcquired = gSaveContext.magicLevel > 0; gSaveContext.isMagicAcquired = gSaveContext.magicLevel > 0;
gSaveContext.isDoubleMagicAcquired = gSaveContext.magicLevel == 2; gSaveContext.isDoubleMagicAcquired = gSaveContext.magicLevel == 2;
} }
@ -203,7 +202,10 @@ void DrawInfoTab() {
} }
int32_t magic = (int32_t)gSaveContext.magic; int32_t magic = (int32_t)gSaveContext.magic;
if (SliderInt("Magic", &magic, intSliderOptionsBase.Min(0).Max(gSaveContext.magicCapacity).Tooltip("Current magic. 48 units per magic level"))) { if (SliderInt("Magic", &magic,
intSliderOptionsBase.Min(0)
.Max(gSaveContext.magicCapacity)
.Tooltip("Current magic. 48 units per magic level"))) {
gSaveContext.magic = (int8_t)magic; gSaveContext.magic = (int8_t)magic;
} }
@ -239,7 +241,8 @@ void DrawInfoTab() {
Tooltip("Total number of deaths"); Tooltip("Total number of deaths");
PopStyleInput(); PopStyleInput();
Checkbox("Has BGS", (bool*) &gSaveContext.bgsFlag, checkboxOptionsBase.Tooltip("Is Biggoron sword unlocked? Replaces Giant's knife")); Checkbox("Has BGS", (bool*)&gSaveContext.bgsFlag,
checkboxOptionsBase.Tooltip("Is Biggoron sword unlocked? Replaces Giant's knife"));
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::InputScalar("Sword Health", ImGuiDataType_U16, &gSaveContext.swordHealth); ImGui::InputScalar("Sword Health", ImGuiDataType_U16, &gSaveContext.swordHealth);
@ -288,24 +291,24 @@ void DrawInfoTab() {
Combobox("Audio", &gSaveContext.audioSetting, audioMap, comboboxOptionsBase.Tooltip("Sound setting")); Combobox("Audio", &gSaveContext.audioSetting, audioMap, comboboxOptionsBase.Tooltip("Sound setting"));
Checkbox("64 DD file?", (bool*) &gSaveContext.n64ddFlag, checkboxOptionsBase.Tooltip("WARNING! If you save, your file may be locked! Use caution!")); Checkbox("64 DD file?", (bool*)&gSaveContext.n64ddFlag,
checkboxOptionsBase.Tooltip("WARNING! If you save, your file may be locked! Use caution!"));
Combobox("Z Target Mode", &gSaveContext.zTargetSetting, zTargetMap, comboboxOptionsBase.Tooltip("Z-Targeting behavior")); Combobox("Z Target Mode", &gSaveContext.zTargetSetting, zTargetMap,
comboboxOptionsBase.Tooltip("Z-Targeting behavior"));
if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT)) { if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT)) {
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::InputScalar("Triforce Pieces", ImGuiDataType_U8, &gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected); ImGui::InputScalar("Triforce Pieces", ImGuiDataType_U8,
&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected);
Tooltip("Currently obtained Triforce Pieces. For Triforce Hunt."); Tooltip("Currently obtained Triforce Pieces. For Triforce Hunt.");
PopStyleInput(); PopStyleInput();
} }
ImGui::PushItemWidth(ImGui::GetFontSize() * 10); ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
static std::array<const char*, 7> minigameHS = { "Horseback Archery", static std::array<const char*, 7> minigameHS = { "Horseback Archery", "Big Poe Points",
"Big Poe Points", "Fishing", "Malon's Obstacle Course",
"Fishing", "Running Man Race", "?",
"Malon's Obstacle Course",
"Running Man Race",
"?",
"Dampe's Race" }; "Dampe's Race" };
if (ImGui::TreeNode("Minigames")) { if (ImGui::TreeNode("Minigames")) {
@ -322,7 +325,8 @@ void DrawInfoTab() {
Tooltip(fishMsg); Tooltip(fishMsg);
PopStyleInput(); PopStyleInput();
bool FishBool = gSaveContext.highScores[i] & 0x80; bool FishBool = gSaveContext.highScores[i] & 0x80;
if (Checkbox("Cheated as Child", &FishBool, checkboxOptionsBase.Tooltip("Used the Sinking lure to catch it."))) { if (Checkbox("Cheated as Child", &FishBool,
checkboxOptionsBase.Tooltip("Used the Sinking lure to catch it."))) {
gSaveContext.highScores[i] &= ~0x80; gSaveContext.highScores[i] &= ~0x80;
gSaveContext.highScores[i] |= (0x80 * FishBool); gSaveContext.highScores[i] |= (0x80 * FishBool);
} }
@ -336,32 +340,41 @@ void DrawInfoTab() {
Tooltip(fishMsg); Tooltip(fishMsg);
PopStyleInput(); PopStyleInput();
FishBool = gSaveContext.highScores[i] & 0x80000000; FishBool = gSaveContext.highScores[i] & 0x80000000;
if (Checkbox("Cheated as Adult", &FishBool, checkboxOptionsBase.Tooltip("Used the Sinking lure to catch it."))) { if (Checkbox("Cheated as Adult", &FishBool,
checkboxOptionsBase.Tooltip("Used the Sinking lure to catch it."))) {
gSaveContext.highScores[i] &= ~0x80000000; gSaveContext.highScores[i] &= ~0x80000000;
gSaveContext.highScores[i] |= (0x80000000 * FishBool); gSaveContext.highScores[i] |= (0x80000000 * FishBool);
} }
FishBool = gSaveContext.highScores[i] & 0x100; FishBool = gSaveContext.highScores[i] & 0x100;
if (Checkbox("Played as Child", &FishBool, checkboxOptionsBase.Tooltip("Played at least one game as a child"))) { if (Checkbox("Played as Child", &FishBool,
checkboxOptionsBase.Tooltip("Played at least one game as a child"))) {
gSaveContext.highScores[i] &= ~0x100; gSaveContext.highScores[i] &= ~0x100;
gSaveContext.highScores[i] |= (0x100 * FishBool); gSaveContext.highScores[i] |= (0x100 * FishBool);
} }
FishBool = gSaveContext.highScores[i] & 0x200; FishBool = gSaveContext.highScores[i] & 0x200;
if (Checkbox("Played as Adult", &FishBool, checkboxOptionsBase.Tooltip("Played at least one game as an adult"))) { if (Checkbox("Played as Adult", &FishBool,
checkboxOptionsBase.Tooltip("Played at least one game as an adult"))) {
gSaveContext.highScores[i] &= ~0x200; gSaveContext.highScores[i] &= ~0x200;
gSaveContext.highScores[i] |= (0x200 * FishBool); gSaveContext.highScores[i] |= (0x200 * FishBool);
} }
FishBool = gSaveContext.highScores[i] & 0x400; FishBool = gSaveContext.highScores[i] & 0x400;
if (Checkbox("Got Prize as Child", &FishBool, checkboxOptionsBase.Tooltip("Got the prize item (Heart Piece, unless rando.)\nunlocks Sinking Lure for Child Link."))) { if (Checkbox(
"Got Prize as Child", &FishBool,
checkboxOptionsBase.Tooltip(
"Got the prize item (Heart Piece, unless rando.)\nunlocks Sinking Lure for Child Link."))) {
gSaveContext.highScores[i] &= ~0x400; gSaveContext.highScores[i] &= ~0x400;
gSaveContext.highScores[i] |= (0x400 * FishBool); gSaveContext.highScores[i] |= (0x400 * FishBool);
} }
FishBool = gSaveContext.highScores[i] & 0x800; FishBool = gSaveContext.highScores[i] & 0x800;
if (Checkbox("Got Prize as Adult", &FishBool, checkboxOptionsBase.Tooltip("Got the prize item (Golden Scale, unless rando.)\nUnlocks Sinking Lure for Adult Link."))) { if (Checkbox("Got Prize as Adult", &FishBool,
checkboxOptionsBase.Tooltip("Got the prize item (Golden Scale, unless rando.)\nUnlocks "
"Sinking Lure for Adult Link."))) {
gSaveContext.highScores[i] &= ~0x800; gSaveContext.highScores[i] &= ~0x800;
gSaveContext.highScores[i] |= (0x800 * FishBool); gSaveContext.highScores[i] |= (0x800 * FishBool);
} }
FishBool = gSaveContext.highScores[i] & 0x1000; FishBool = gSaveContext.highScores[i] & 0x1000;
if (Checkbox("Stole Owner's Hat", &FishBool, checkboxOptionsBase.Tooltip("The owner's now visibly bald when Adult Link."))) { if (Checkbox("Stole Owner's Hat", &FishBool,
checkboxOptionsBase.Tooltip("The owner's now visibly bald when Adult Link."))) {
gSaveContext.highScores[i] &= ~0x1000; gSaveContext.highScores[i] &= ~0x1000;
gSaveContext.highScores[i] |= (0x1000 * FishBool); gSaveContext.highScores[i] |= (0x1000 * FishBool);
} }
@ -402,7 +415,9 @@ void DrawBGSItemFlag(uint8_t itemID) {
void DrawInventoryTab() { void DrawInventoryTab() {
static bool restrictToValid = true; static bool restrictToValid = true;
Checkbox("Restrict to valid items", &restrictToValid, checkboxOptionsBase.Tooltip("Restricts items and ammo to only what is possible to legally acquire in-game")); Checkbox(
"Restrict to valid items", &restrictToValid,
checkboxOptionsBase.Tooltip("Restricts items and ammo to only what is possible to legally acquire in-game"));
for (int32_t y = 0; y < 4; y++) { for (int32_t y = 0; y < 4; y++) {
for (int32_t x = 0; x < 6; x++) { for (int32_t x = 0; x < 6; x++) {
@ -420,7 +435,9 @@ void DrawInventoryTab() {
PushStyleButton(Colors::DarkGray); PushStyleButton(Colors::DarkGray);
if (item != ITEM_NONE) { if (item != ITEM_NONE) {
const ItemMapEntry& slotEntry = itemMapping.find(item)->second; const ItemMapEntry& slotEntry = itemMapping.find(item)->second;
auto ret = ImGui::ImageButton(slotEntry.name.c_str(), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), auto ret = ImGui::ImageButton(
slotEntry.name.c_str(),
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name),
ImVec2(48.0f, 48.0f), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(48.0f, 48.0f), ImVec2(0, 0), ImVec2(1, 1));
if (ret) { if (ret) {
selectedIndex = index; selectedIndex = index;
@ -437,7 +454,8 @@ void DrawInventoryTab() {
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
if (ImGui::BeginPopup(itemPopupPicker)) { if (ImGui::BeginPopup(itemPopupPicker)) {
PushStyleButton(Colors::DarkGray); PushStyleButton(Colors::DarkGray);
if (ImGui::Button("##itemNonePicker", ImVec2(IMAGE_SIZE, IMAGE_SIZE) + ImGui::GetStyle().FramePadding * 2)) { if (ImGui::Button("##itemNonePicker",
ImVec2(IMAGE_SIZE, IMAGE_SIZE) + ImGui::GetStyle().FramePadding * 2)) {
gSaveContext.inventory.items[selectedIndex] = ITEM_NONE; gSaveContext.inventory.items[selectedIndex] = ITEM_NONE;
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
@ -468,7 +486,9 @@ void DrawInventoryTab() {
} }
const ItemMapEntry& slotEntry = possibleItems[pickerIndex]; const ItemMapEntry& slotEntry = possibleItems[pickerIndex];
PushStyleButton(Colors::DarkGray); PushStyleButton(Colors::DarkGray);
auto ret = ImGui::ImageButton(slotEntry.name.c_str(), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), auto ret = ImGui::ImageButton(
slotEntry.name.c_str(),
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name),
ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1));
PopStyleButton(); PopStyleButton();
if (ret) { if (ret) {
@ -501,7 +521,8 @@ void DrawInventoryTab() {
ImGui::PushItemWidth(IMAGE_SIZE); ImGui::PushItemWidth(IMAGE_SIZE);
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[item].name), ImVec2(IMAGE_SIZE, IMAGE_SIZE)); ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[item].name),
ImVec2(IMAGE_SIZE, IMAGE_SIZE));
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::InputScalar("##ammoInput", ImGuiDataType_S8, &AMMO(item)); ImGui::InputScalar("##ammoInput", ImGuiDataType_S8, &AMMO(item));
PopStyleInput(); PopStyleInput();
@ -514,8 +535,8 @@ void DrawInventoryTab() {
// Trade quest flags are only used when shuffling the trade sequence, so // Trade quest flags are only used when shuffling the trade sequence, so
// don't show this if it isn't needed. // don't show this if it isn't needed.
if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE) if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE) &&
&& ImGui::TreeNode("Adult trade quest items")) { ImGui::TreeNode("Adult trade quest items")) {
for (int i = ITEM_POCKET_EGG; i <= ITEM_CLAIM_CHECK; i++) { for (int i = ITEM_POCKET_EGG; i <= ITEM_CLAIM_CHECK; i++) {
DrawBGSItemFlag(i); DrawBGSItemFlag(i);
} }
@ -560,36 +581,45 @@ void DrawFlagsTab() {
if (gPlayState != nullptr) { if (gPlayState != nullptr) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("stateFlags1"); ImGui::Text("stateFlags1");
DrawFlagArray32("stateFlags1", player->stateFlags1, THEME_COLOR); DrawFlagArray32("stateFlags1", player->stateFlags1, THEME_COLOR);
}, "stateFlags1"); },
"stateFlags1");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("stateFlags2"); ImGui::Text("stateFlags2");
DrawFlagArray32("stateFlags2", player->stateFlags2, THEME_COLOR); DrawFlagArray32("stateFlags2", player->stateFlags2, THEME_COLOR);
}, "stateFlags2"); },
"stateFlags2");
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("stateFlags3"); ImGui::Text("stateFlags3");
DrawFlagArray8("stateFlags3", player->stateFlags3, THEME_COLOR); DrawFlagArray8("stateFlags3", player->stateFlags3, THEME_COLOR);
}, "stateFlags3"); },
"stateFlags3");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("unk_6AE_rotFlags"); ImGui::Text("unk_6AE_rotFlags");
DrawFlagArray16("unk_6AE_rotFlags", player->unk_6AE_rotFlags, THEME_COLOR); DrawFlagArray16("unk_6AE_rotFlags", player->unk_6AE_rotFlags, THEME_COLOR);
}, "unk_6AE_rotFlags"); },
"unk_6AE_rotFlags");
} }
ImGui::TreePop(); ImGui::TreePop();
} }
if (ImGui::TreeNode("Current Scene")) { if (ImGui::TreeNode("Current Scene")) {
if (gPlayState != nullptr) { if (gPlayState != nullptr) {
ActorContext* act = &gPlayState->actorCtx; ActorContext* act = &gPlayState->actorCtx;
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Switch"); ImGui::Text("Switch");
InsertHelpHoverText("Permanently-saved switch flags"); InsertHelpHoverText("Permanently-saved switch flags");
if (Button("Set All##Switch", buttonOptionsBase.Tooltip(""))) { if (Button("Set All##Switch", buttonOptionsBase.Tooltip(""))) {
@ -600,11 +630,13 @@ void DrawFlagsTab() {
act->flags.swch = 0; act->flags.swch = 0;
} }
DrawFlagArray32("Switch", act->flags.swch, THEME_COLOR); DrawFlagArray32("Switch", act->flags.swch, THEME_COLOR);
}, "Switch"); },
"Switch");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Temp Switch"); ImGui::Text("Temp Switch");
InsertHelpHoverText("Temporary switch flags. Unset on scene transitions"); InsertHelpHoverText("Temporary switch flags. Unset on scene transitions");
if (Button("Set All##Temp Switch", buttonOptionsBase.Tooltip(""))) { if (Button("Set All##Temp Switch", buttonOptionsBase.Tooltip(""))) {
@ -615,9 +647,11 @@ void DrawFlagsTab() {
act->flags.tempSwch = 0; act->flags.tempSwch = 0;
} }
DrawFlagArray32("Temp Switch", act->flags.tempSwch, THEME_COLOR); DrawFlagArray32("Temp Switch", act->flags.tempSwch, THEME_COLOR);
}, "Temp Switch"); },
"Temp Switch");
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Clear"); ImGui::Text("Clear");
InsertHelpHoverText("Permanently-saved room-clear flags"); InsertHelpHoverText("Permanently-saved room-clear flags");
if (Button("Set All##Clear", buttonOptionsBase.Tooltip(""))) { if (Button("Set All##Clear", buttonOptionsBase.Tooltip(""))) {
@ -628,11 +662,13 @@ void DrawFlagsTab() {
act->flags.clear = 0; act->flags.clear = 0;
} }
DrawFlagArray32("Clear", act->flags.clear, THEME_COLOR); DrawFlagArray32("Clear", act->flags.clear, THEME_COLOR);
}, "Clear"); },
"Clear");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Temp Clear"); ImGui::Text("Temp Clear");
InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions"); InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions");
if (Button("Set All##Temp Clear", buttonOptionsBase.Tooltip(""))) { if (Button("Set All##Temp Clear", buttonOptionsBase.Tooltip(""))) {
@ -643,9 +679,11 @@ void DrawFlagsTab() {
act->flags.tempClear = 0; act->flags.tempClear = 0;
} }
DrawFlagArray32("Temp Clear", act->flags.tempClear, THEME_COLOR); DrawFlagArray32("Temp Clear", act->flags.tempClear, THEME_COLOR);
}, "Temp Clear"); },
"Temp Clear");
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Collect"); ImGui::Text("Collect");
InsertHelpHoverText("Permanently-saved collect flags"); InsertHelpHoverText("Permanently-saved collect flags");
if (Button("Set All##Collect", buttonOptionsBase.Tooltip(""))) { if (Button("Set All##Collect", buttonOptionsBase.Tooltip(""))) {
@ -656,11 +694,13 @@ void DrawFlagsTab() {
act->flags.collect = 0; act->flags.collect = 0;
} }
DrawFlagArray32("Collect", act->flags.collect, THEME_COLOR); DrawFlagArray32("Collect", act->flags.collect, THEME_COLOR);
}, "Collect"); },
"Collect");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Temp Collect"); ImGui::Text("Temp Collect");
InsertHelpHoverText("Temporary collect flags. Unset on scene transitions"); InsertHelpHoverText("Temporary collect flags. Unset on scene transitions");
if (Button("Set All##Temp Collect", buttonOptionsBase.Tooltip(""))) { if (Button("Set All##Temp Collect", buttonOptionsBase.Tooltip(""))) {
@ -671,9 +711,11 @@ void DrawFlagsTab() {
act->flags.tempCollect = 0; act->flags.tempCollect = 0;
} }
DrawFlagArray32("Temp Collect", act->flags.tempCollect, THEME_COLOR); DrawFlagArray32("Temp Collect", act->flags.tempCollect, THEME_COLOR);
}, "Temp Collect"); },
"Temp Collect");
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Chest"); ImGui::Text("Chest");
InsertHelpHoverText("Permanently-saved chest flags"); InsertHelpHoverText("Permanently-saved chest flags");
if (Button("Set All##Chest", buttonOptionsBase.Tooltip(""))) { if (Button("Set All##Chest", buttonOptionsBase.Tooltip(""))) {
@ -684,34 +726,37 @@ void DrawFlagsTab() {
act->flags.chest = 0; act->flags.chest = 0;
} }
DrawFlagArray32("Chest", act->flags.chest, THEME_COLOR); DrawFlagArray32("Chest", act->flags.chest, THEME_COLOR);
}, "Chest"); },
"Chest");
ImGui::SameLine(); ImGui::SameLine();
ImGui::BeginGroup(); ImGui::BeginGroup();
if (Button("Reload Flags", buttonOptionsBase.Tooltip("Load flags from saved scene flags. Normally happens on scene load"))) { if (Button("Reload Flags", buttonOptionsBase.Tooltip(
"Load flags from saved scene flags. Normally happens on scene load"))) {
act->flags.swch = gSaveContext.sceneFlags[gPlayState->sceneNum].swch; act->flags.swch = gSaveContext.sceneFlags[gPlayState->sceneNum].swch;
act->flags.clear = gSaveContext.sceneFlags[gPlayState->sceneNum].clear; act->flags.clear = gSaveContext.sceneFlags[gPlayState->sceneNum].clear;
act->flags.collect = gSaveContext.sceneFlags[gPlayState->sceneNum].collect; act->flags.collect = gSaveContext.sceneFlags[gPlayState->sceneNum].collect;
act->flags.chest = gSaveContext.sceneFlags[gPlayState->sceneNum].chest; act->flags.chest = gSaveContext.sceneFlags[gPlayState->sceneNum].chest;
} }
if (Button("Save Flags", buttonOptionsBase.Tooltip("Save current scene flags. Normally happens on scene exit"))) { if (Button("Save Flags",
buttonOptionsBase.Tooltip("Save current scene flags. Normally happens on scene exit"))) {
gSaveContext.sceneFlags[gPlayState->sceneNum].swch = act->flags.swch; gSaveContext.sceneFlags[gPlayState->sceneNum].swch = act->flags.swch;
gSaveContext.sceneFlags[gPlayState->sceneNum].clear = act->flags.clear; gSaveContext.sceneFlags[gPlayState->sceneNum].clear = act->flags.clear;
gSaveContext.sceneFlags[gPlayState->sceneNum].collect = act->flags.collect; gSaveContext.sceneFlags[gPlayState->sceneNum].collect = act->flags.collect;
gSaveContext.sceneFlags[gPlayState->sceneNum].chest = act->flags.chest; gSaveContext.sceneFlags[gPlayState->sceneNum].chest = act->flags.chest;
} }
if (Button("Clear Flags", buttonOptionsBase.Tooltip("Clear current scene flags. Reload scene to see changes"))) { if (Button("Clear Flags",
buttonOptionsBase.Tooltip("Clear current scene flags. Reload scene to see changes"))) {
act->flags.swch = 0; act->flags.swch = 0;
act->flags.clear = 0; act->flags.clear = 0;
act->flags.collect = 0; act->flags.collect = 0;
act->flags.chest = 0; act->flags.chest = 0;
} }
ImGui::EndGroup(); ImGui::EndGroup();
} else { } else {
ImGui::Text("Current game state does not have an active scene"); ImGui::Text("Current game state does not have an active scene");
@ -745,52 +790,65 @@ void DrawFlagsTab() {
} }
} }
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Switch"); ImGui::Text("Switch");
InsertHelpHoverText("Switch flags"); InsertHelpHoverText("Switch flags");
DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch, THEME_COLOR); DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch, THEME_COLOR);
}, "Saved Switch"); },
"Saved Switch");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Clear"); ImGui::Text("Clear");
InsertHelpHoverText("Room-clear flags"); InsertHelpHoverText("Room-clear flags");
DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear, THEME_COLOR); DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear, THEME_COLOR);
}, "Saved Clear"); },
"Saved Clear");
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Collect"); ImGui::Text("Collect");
InsertHelpHoverText("Collect flags"); InsertHelpHoverText("Collect flags");
DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect, THEME_COLOR); DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect, THEME_COLOR);
}, "Saved Collect"); },
"Saved Collect");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Chest"); ImGui::Text("Chest");
InsertHelpHoverText("Chest flags"); InsertHelpHoverText("Chest flags");
DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest, THEME_COLOR); DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest, THEME_COLOR);
}, "Saved Chest"); },
"Saved Chest");
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Rooms"); ImGui::Text("Rooms");
InsertHelpHoverText("Flags for visted rooms"); InsertHelpHoverText("Flags for visted rooms");
DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms, THEME_COLOR); DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms, THEME_COLOR);
}, "Saved Rooms"); },
"Saved Rooms");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Floors"); ImGui::Text("Floors");
InsertHelpHoverText("Flags for visted floors"); InsertHelpHoverText("Flags for visted floors");
DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors, THEME_COLOR); DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors, THEME_COLOR);
}, "Saved Floors"); },
"Saved Floors");
ImGui::TreePop(); ImGui::TreePop();
} }
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
size_t selectedGsMap = 0; size_t selectedGsMap = 0;
ImGui::Text("Gold Skulltulas"); ImGui::Text("Gold Skulltulas");
Combobox("Map##Gold Skulltulas", &selectedGsMap, gsMapping, comboboxOptionsBase.Tooltip("")); Combobox("Map##Gold Skulltulas", &selectedGsMap, gsMapping, comboboxOptionsBase.Tooltip(""));
@ -831,10 +889,12 @@ void DrawFlagsTab() {
// If playing a Randomizer Save with Shuffle Skull Tokens on anything other than "Off" we don't want to keep // If playing a Randomizer Save with Shuffle Skull Tokens on anything other than "Off" we don't want to keep
// GS Token Count updated, since Gold Skulltulas killed will not correlate to GS Tokens Collected. // GS Token Count updated, since Gold Skulltulas killed will not correlate to GS Tokens Collected.
if (!(IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF)) { if (!(IS_RANDO &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF)) {
static bool keepGsCountUpdated = true; static bool keepGsCountUpdated = true;
Checkbox("Keep GS Count Updated", &keepGsCountUpdated, Checkbox("Keep GS Count Updated", &keepGsCountUpdated,
checkboxOptionsBase.Tooltip("Automatically adjust the number of gold skulltula tokens acquired based on set flags.")); checkboxOptionsBase.Tooltip(
"Automatically adjust the number of gold skulltula tokens acquired based on set flags."));
int32_t gsCount = 0; int32_t gsCount = 0;
if (keepGsCountUpdated) { if (keepGsCountUpdated) {
for (int32_t gsFlagIndex = 0; gsFlagIndex < 6; gsFlagIndex++) { for (int32_t gsFlagIndex = 0; gsFlagIndex < 6; gsFlagIndex++) {
@ -843,7 +903,8 @@ void DrawFlagsTab() {
gSaveContext.inventory.gsTokens = gsCount; gSaveContext.inventory.gsTokens = gsCount;
} }
} }
}, "Gold Skulltulas"); },
"Gold Skulltulas");
for (int i = 0; i < flagTables.size(); i++) { for (int i = 0; i < flagTables.size(); i++) {
const FlagTable& flagTable = flagTables[i]; const FlagTable& flagTable = flagTables[i];
@ -853,7 +914,8 @@ void DrawFlagsTab() {
if (ImGui::TreeNode(flagTable.name)) { if (ImGui::TreeNode(flagTable.name)) {
for (int j = 0; j < flagTable.size + 1; j++) { for (int j = 0; j < flagTable.size + 1; j++) {
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("%s", fmt::format("{:<2x}", j).c_str()); ImGui::Text("%s", fmt::format("{:<2x}", j).c_str());
switch (flagTable.flagTableType) { switch (flagTable.flagTableType) {
case EVENT_CHECK_INF: case EVENT_CHECK_INF:
@ -872,13 +934,14 @@ void DrawFlagsTab() {
DrawFlagTableArray16(flagTable, j, gSaveContext.ship.randomizerInf[j]); DrawFlagTableArray16(flagTable, j, gSaveContext.ship.randomizerInf[j]);
break; break;
} }
}, flagTable.name); },
flagTable.name);
} }
// make some buttons to help with fishsanity debugging // make some buttons to help with fishsanity debugging
uint8_t fsMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY); uint8_t fsMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
if (flagTable.flagTableType == RANDOMIZER_INF && if (flagTable.flagTableType == RANDOMIZER_INF && fsMode != RO_FISHSANITY_OFF &&
fsMode != RO_FISHSANITY_OFF && fsMode != RO_FISHSANITY_OVERWORLD) { fsMode != RO_FISHSANITY_OVERWORLD) {
if (ImGui::Button("Catch All (Child)")) { if (ImGui::Button("Catch All (Child)")) {
for (int k = RAND_INF_CHILD_FISH_1; k <= RAND_INF_CHILD_LOACH_2; k++) { for (int k = RAND_INF_CHILD_FISH_1; k <= RAND_INF_CHILD_LOACH_2; k++) {
Flags_SetRandomizerInf((RandomizerInf)k); Flags_SetRandomizerInf((RandomizerInf)k);
@ -940,7 +1003,8 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const
uint8_t item = items[CUR_UPG_VALUE(categoryId)]; uint8_t item = items[CUR_UPG_VALUE(categoryId)];
if (item != ITEM_NONE) { if (item != ITEM_NONE) {
const ItemMapEntry& slotEntry = itemMapping[item]; const ItemMapEntry& slotEntry = itemMapping[item];
if (ImGui::ImageButton(slotEntry.name.c_str(), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), if (ImGui::ImageButton(slotEntry.name.c_str(),
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name),
ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1))) { ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1))) {
ImGui::OpenPopup(upgradePopupPicker); ImGui::OpenPopup(upgradePopupPicker);
} }
@ -960,14 +1024,17 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const
PushStyleButton(Colors::DarkGray); PushStyleButton(Colors::DarkGray);
if (items[pickerIndex] == ITEM_NONE) { if (items[pickerIndex] == ITEM_NONE) {
if (ImGui::Button("##upgradePopupPicker", ImVec2(IMAGE_SIZE, IMAGE_SIZE) + ImGui::GetStyle().FramePadding * 2)) { if (ImGui::Button("##upgradePopupPicker",
ImVec2(IMAGE_SIZE, IMAGE_SIZE) + ImGui::GetStyle().FramePadding * 2)) {
Inventory_ChangeUpgrade(categoryId, pickerIndex); Inventory_ChangeUpgrade(categoryId, pickerIndex);
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
Tooltip("None"); Tooltip("None");
} else { } else {
const ItemMapEntry& slotEntry = itemMapping[items[pickerIndex]]; const ItemMapEntry& slotEntry = itemMapping[items[pickerIndex]];
auto ret = ImGui::ImageButton(slotEntry.name.c_str(), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), auto ret = ImGui::ImageButton(
slotEntry.name.c_str(),
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name),
ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1));
if (ret) { if (ret) {
Inventory_ChangeUpgrade(categoryId, pickerIndex); Inventory_ChangeUpgrade(categoryId, pickerIndex);
@ -1003,7 +1070,9 @@ void DrawEquipmentTab() {
bool hasEquip = (bitMask & gSaveContext.inventory.equipment) != 0; bool hasEquip = (bitMask & gSaveContext.inventory.equipment) != 0;
const ItemMapEntry& entry = itemMapping[equipmentValues[i]]; const ItemMapEntry& entry = itemMapping[equipmentValues[i]];
PushStyleButton(Colors::DarkGray); PushStyleButton(Colors::DarkGray);
auto ret = ImGui::ImageButton(entry.name.c_str(), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasEquip ? entry.name : entry.nameFaded), auto ret = ImGui::ImageButton(entry.name.c_str(),
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
hasEquip ? entry.name : entry.nameFaded),
ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1));
if (ret) { if (ret) {
if (hasEquip) { if (hasEquip) {
@ -1103,7 +1172,9 @@ void DrawQuestItemButton(uint32_t item) {
uint32_t bitMask = 1 << entry.id; uint32_t bitMask = 1 << entry.id;
bool hasQuestItem = (bitMask & gSaveContext.inventory.questItems) != 0; bool hasQuestItem = (bitMask & gSaveContext.inventory.questItems) != 0;
PushStyleButton(Colors::DarkGray); PushStyleButton(Colors::DarkGray);
auto ret = ImGui::ImageButton(entry.name.c_str(), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem ? entry.name : entry.nameFaded), auto ret = ImGui::ImageButton(entry.name.c_str(),
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
hasQuestItem ? entry.name : entry.nameFaded),
ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1));
if (ret) { if (ret) {
if (hasQuestItem) { if (hasQuestItem) {
@ -1122,7 +1193,9 @@ void DrawDungeonItemButton(uint32_t item, uint32_t scene) {
uint32_t bitMask = 1 << (entry.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential uint32_t bitMask = 1 << (entry.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential
bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[scene]) != 0; bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[scene]) != 0;
PushStyleButton(Colors::DarkGray); PushStyleButton(Colors::DarkGray);
auto ret = ImGui::ImageButton(entry.name.c_str(), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem ? entry.name : entry.nameFaded), auto ret = ImGui::ImageButton(
entry.name.c_str(),
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem ? entry.name : entry.nameFaded),
ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(IMAGE_SIZE, IMAGE_SIZE), ImVec2(0, 0), ImVec2(1, 1));
if (ret) { if (ret) {
if (hasItem) { if (hasItem) {
@ -1168,7 +1241,9 @@ void DrawQuestStatusTab() {
uint32_t bitMask = 1 << entry.id; uint32_t bitMask = 1 << entry.id;
bool hasQuestItem = (bitMask & gSaveContext.inventory.questItems) != 0; bool hasQuestItem = (bitMask & gSaveContext.inventory.questItems) != 0;
PushStyleButton(Colors::DarkGray); PushStyleButton(Colors::DarkGray);
auto ret = ImGui::ImageButton(entry.name.c_str(), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasQuestItem ? entry.name : entry.nameFaded), auto ret = ImGui::ImageButton(entry.name.c_str(),
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
hasQuestItem ? entry.name : entry.nameFaded),
ImVec2(32.0f, 48.0f), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(32.0f, 48.0f), ImVec2(0, 0), ImVec2(1, 1));
if (ret) { if (ret) {
if (hasQuestItem) { if (hasQuestItem) {
@ -1211,7 +1286,8 @@ void DrawQuestStatusTab() {
InsertHelpHoverText("The number of pieces of heart acquired towards the next heart container"); InsertHelpHoverText("The number of pieces of heart acquired towards the next heart container");
PopStyleCombobox(); PopStyleCombobox();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Dungeon Items"); ImGui::Text("Dungeon Items");
static int32_t dungeonItemsScene = SCENE_DEKU_TREE; static int32_t dungeonItemsScene = SCENE_DEKU_TREE;
@ -1236,19 +1312,24 @@ void DrawQuestStatusTab() {
if (dungeonItemsScene != SCENE_JABU_JABU_BOSS) { if (dungeonItemsScene != SCENE_JABU_JABU_BOSS) {
float lineHeight = ImGui::GetTextLineHeightWithSpacing(); float lineHeight = ImGui::GetTextLineHeightWithSpacing();
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[ITEM_KEY_SMALL].name), ImVec2(lineHeight, lineHeight)); ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
itemMapping[ITEM_KEY_SMALL].name),
ImVec2(lineHeight, lineHeight));
ImGui::SameLine(); ImGui::SameLine();
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
if (ImGui::InputScalar("##Keys", ImGuiDataType_S8, gSaveContext.inventory.dungeonKeys + dungeonItemsScene)) { if (ImGui::InputScalar("##Keys", ImGuiDataType_S8,
gSaveContext.ship.stats.dungeonKeys[dungeonItemsScene] = gSaveContext.inventory.dungeonKeys[dungeonItemsScene]; gSaveContext.inventory.dungeonKeys + dungeonItemsScene)) {
gSaveContext.ship.stats.dungeonKeys[dungeonItemsScene] =
gSaveContext.inventory.dungeonKeys[dungeonItemsScene];
}; };
PopStyleInput(); PopStyleInput();
} else { } else {
// dungeonItems is size 20 but dungeonKeys is size 19, so there are no keys for the last scene (Barinade's Lair) // dungeonItems is size 20 but dungeonKeys is size 19, so there are no keys for the last scene
// (Barinade's Lair)
ImGui::Text("Barinade's Lair does not have small keys"); ImGui::Text("Barinade's Lair does not have small keys");
} }
}, "Dungeon Items"); },
"Dungeon Items");
} }
void DrawPlayerTab() { void DrawPlayerTab() {
@ -1327,16 +1408,19 @@ void DrawPlayerTab() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Link's Position"); ImGui::Text("Link's Position");
ImGui::PushItemWidth(ImGui::GetFontSize() * 12); ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
ImGui::InputScalar("X##Pos", ImGuiDataType_Float, &player->actor.world.pos.x); ImGui::InputScalar("X##Pos", ImGuiDataType_Float, &player->actor.world.pos.x);
ImGui::InputScalar("Y##Pos", ImGuiDataType_Float, &player->actor.world.pos.y); ImGui::InputScalar("Y##Pos", ImGuiDataType_Float, &player->actor.world.pos.y);
ImGui::InputScalar("Z##Pos", ImGuiDataType_Float, &player->actor.world.pos.z); ImGui::InputScalar("Z##Pos", ImGuiDataType_Float, &player->actor.world.pos.z);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
}, "Link's Position"); },
"Link's Position");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Link's Rotation"); ImGui::Text("Link's Rotation");
InsertHelpHoverText("For Link's rotation in relation to the world"); InsertHelpHoverText("For Link's rotation in relation to the world");
ImGui::PushItemWidth(ImGui::GetFontSize() * 12); ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
@ -1344,9 +1428,11 @@ void DrawPlayerTab() {
ImGui::InputScalar("Y##Rot", ImGuiDataType_S16, &player->actor.world.rot.y); ImGui::InputScalar("Y##Rot", ImGuiDataType_S16, &player->actor.world.rot.y);
ImGui::InputScalar("Z##Rot", ImGuiDataType_S16, &player->actor.world.rot.z); ImGui::InputScalar("Z##Rot", ImGuiDataType_S16, &player->actor.world.rot.z);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
}, "Link's Rotation"); },
"Link's Rotation");
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Link's Model Rotation"); ImGui::Text("Link's Model Rotation");
InsertHelpHoverText("For Link's actual model"); InsertHelpHoverText("For Link's actual model");
ImGui::PushItemWidth(ImGui::GetFontSize() * 12); ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
@ -1354,7 +1440,8 @@ void DrawPlayerTab() {
ImGui::InputScalar("Y##ModRot", ImGuiDataType_S16, &player->actor.shape.rot.y); ImGui::InputScalar("Y##ModRot", ImGuiDataType_S16, &player->actor.shape.rot.y);
ImGui::InputScalar("Z##ModRot", ImGuiDataType_S16, &player->actor.shape.rot.z); ImGui::InputScalar("Z##ModRot", ImGuiDataType_S16, &player->actor.shape.rot.z);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
}, "Link's Model Rotation"); },
"Link's Model Rotation");
ImGui::InputScalar("Linear Velocity", ImGuiDataType_Float, &player->linearVelocity); ImGui::InputScalar("Linear Velocity", ImGuiDataType_Float, &player->linearVelocity);
InsertHelpHoverText("Link's speed along the XZ plane"); InsertHelpHoverText("Link's speed along the XZ plane");
@ -1386,7 +1473,8 @@ void DrawPlayerTab() {
PopStyleCombobox(); PopStyleCombobox();
ImGui::Separator(); ImGui::Separator();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
PushStyleCombobox(THEME_COLOR); PushStyleCombobox(THEME_COLOR);
ImGui::Text("Link's Current Equipment"); ImGui::Text("Link's Current Equipment");
ImGui::PushItemWidth(ImGui::GetFontSize() * 12); ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
@ -1413,8 +1501,7 @@ void DrawPlayerTab() {
} }
player->currentSwordItemId = ITEM_SWORD_BGS; player->currentSwordItemId = ITEM_SWORD_BGS;
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS; gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
} } else {
else {
if (gSaveContext.swordHealth < 8) { if (gSaveContext.swordHealth < 8) {
gSaveContext.swordHealth = 8; gSaveContext.swordHealth = 8;
} }
@ -1430,7 +1517,6 @@ void DrawPlayerTab() {
Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_MASTER); Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_MASTER);
} }
ImGui::EndCombo(); ImGui::EndCombo();
} }
if (ImGui::BeginCombo("Shield", curShield)) { if (ImGui::BeginCombo("Shield", curShield)) {
if (ImGui::Selectable("None")) { if (ImGui::Selectable("None")) {
@ -1485,11 +1571,13 @@ void DrawPlayerTab() {
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();
PopStyleCombobox(); PopStyleCombobox();
}, "Current Equipment"); },
"Current Equipment");
ImGui::SameLine(); ImGui::SameLine();
ImU16 one = 1; ImU16 one = 1;
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::Text("Current Items"); ImGui::Text("Current Items");
@ -1499,11 +1587,13 @@ void DrawPlayerTab() {
ImGui::InputScalar("C Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[3], &one, NULL); ImGui::InputScalar("C Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[3], &one, NULL);
PopStyleInput(); PopStyleInput();
ImGui::PopItemWidth(); ImGui::PopItemWidth();
}, "Current Items"); },
"Current Items");
if (CVarGetInteger(CVAR_ENHANCEMENT("DpadEquips"), 0)) { if (CVarGetInteger(CVAR_ENHANCEMENT("DpadEquips"), 0)) {
ImGui::SameLine(); ImGui::SameLine();
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
ImGui::Text("Current D-pad Items"); ImGui::Text("Current D-pad Items");
@ -1511,10 +1601,12 @@ void DrawPlayerTab() {
ImGui::InputScalar("D-pad Up ", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[4], &one, NULL); ImGui::InputScalar("D-pad Up ", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[4], &one, NULL);
ImGui::InputScalar("D-pad Down", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[5], &one, NULL); ImGui::InputScalar("D-pad Down", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[5], &one, NULL);
ImGui::InputScalar("D-pad Left", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[6], &one, NULL); ImGui::InputScalar("D-pad Left", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[6], &one, NULL);
ImGui::InputScalar("D-pad Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[7], &one, NULL); ImGui::InputScalar("D-pad Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[7], &one,
NULL);
PopStyleInput(); PopStyleInput();
ImGui::PopItemWidth(); ImGui::PopItemWidth();
}, "Current D-pad Items"); },
"Current D-pad Items");
} }
ImGui::Text("Player State"); ImGui::Text("Player State");
@ -1524,7 +1616,8 @@ void DrawPlayerTab() {
for (int j = 0; j <= 2; j++) { for (int j = 0; j <= 2; j++) {
std::string label = fmt::format("State Flags {}", j + 1); std::string label = fmt::format("State Flags {}", j + 1);
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("%s", label.c_str()); ImGui::Text("%s", label.c_str());
std::vector<std::string> state = flag_strs[j]; std::vector<std::string> state = flag_strs[j];
for (int i = 0; i <= 31; i++) { for (int i = 0; i <= 31; i++) {
@ -1533,13 +1626,16 @@ void DrawPlayerTab() {
ImGui::Text("%s", state[i].c_str()); ImGui::Text("%s", state[i].c_str());
} }
} }
}, label.c_str()); },
label.c_str());
ImGui::SameLine(); ImGui::SameLine();
} }
DrawGroupWithBorder([&]() { DrawGroupWithBorder(
[&]() {
ImGui::Text("Sword"); ImGui::Text("Sword");
ImGui::Text(" %d", player->meleeWeaponState); ImGui::Text(" %d", player->meleeWeaponState);
}, "Sword"); },
"Sword");
} else { } else {
ImGui::Text("Global Context needed for player info!"); ImGui::Text("Global Context needed for player info!");
@ -1550,7 +1646,10 @@ void ResetBaseOptions() {
intSliderOptionsBase.Color(THEME_COLOR).Size({ 320.0f, 0.0f }).Tooltip(""); intSliderOptionsBase.Color(THEME_COLOR).Size({ 320.0f, 0.0f }).Tooltip("");
buttonOptionsBase.Color(THEME_COLOR).Size(Sizes::Inline).Tooltip(""); buttonOptionsBase.Color(THEME_COLOR).Size(Sizes::Inline).Tooltip("");
checkboxOptionsBase.Color(THEME_COLOR).Tooltip(""); checkboxOptionsBase.Color(THEME_COLOR).Tooltip("");
comboboxOptionsBase.Color(THEME_COLOR).ComponentAlignment(ComponentAlignments::Left).LabelPosition(LabelPositions::Near).Tooltip(""); comboboxOptionsBase.Color(THEME_COLOR)
.ComponentAlignment(ComponentAlignments::Left)
.LabelPosition(LabelPositions::Near)
.Tooltip("");
} }
void SaveEditorWindow::DrawElement() { void SaveEditorWindow::DrawElement() {
@ -1601,4 +1700,5 @@ void SaveEditorWindow::DrawElement() {
PopStyleTabs(); PopStyleTabs();
} }
void SaveEditorWindow::InitElement() {} void SaveEditorWindow::InitElement() {
}

View file

@ -26,7 +26,10 @@ typedef struct {
// Reference https://tcrf.net/Proto:The_Legend_of_Zelda:_Ocarina_of_Time_Master_Quest/Event_Editor // Reference https://tcrf.net/Proto:The_Legend_of_Zelda:_Ocarina_of_Time_Master_Quest/Event_Editor
// The source was last referenced on 2022-09-03 and had a last updated value of 2020-05-02 // The source was last referenced on 2022-09-03 and had a last updated value of 2020-05-02
const std::vector<FlagTable> flagTables = { const std::vector<FlagTable> flagTables = {
{ "Event Check Inf Flags", EVENT_CHECK_INF, 0x0D, { { "Event Check Inf Flags",
EVENT_CHECK_INF,
0x0D,
{
{ 0x02, "First Spoke to Mido" }, { 0x02, "First Spoke to Mido" },
{ 0x03, "Complained About Mido to Saria" }, { 0x03, "Complained About Mido to Saria" },
{ 0x04, "Showed Mido Sword & Shield" }, { 0x04, "Showed Mido Sword & Shield" },
@ -162,7 +165,10 @@ const std::vector<FlagTable> flagTables = {
{ 0xDD, "Obtained Skulltula House's Bombchu" }, { 0xDD, "Obtained Skulltula House's Bombchu" },
{ 0xDE, "Obtained Skulltula House's Piece of Heart" }, { 0xDE, "Obtained Skulltula House's Piece of Heart" },
} }, } },
{ "Item Get Inf Flags", ITEM_GET_INF, 0x03, { { "Item Get Inf Flags",
ITEM_GET_INF,
0x03,
{
{ 0x02, "Obtained Super Cucco Bottle" }, { 0x02, "Obtained Super Cucco Bottle" },
{ 0x03, "Bought Bombchu (Shelf 2: Top Right)" }, { 0x03, "Bought Bombchu (Shelf 2: Top Right)" },
{ 0x04, "Bought Bombchu (Shelf 1: Bot. Right)" }, { 0x04, "Bought Bombchu (Shelf 1: Bot. Right)" },
@ -207,7 +213,10 @@ const std::vector<FlagTable> flagTables = {
{ 0x3B, "Sold Bunny Hood" }, { 0x3B, "Sold Bunny Hood" },
{ 0x3F, "Obtained Mask of Truth" }, { 0x3F, "Obtained Mask of Truth" },
} }, } },
{ "Inf Flags", INF_TABLE, 0x1D, { { "Inf Flags",
INF_TABLE,
0x1D,
{
{ 0x00, "Greeted by Saria" }, { 0x00, "Greeted by Saria" },
{ 0x01, "Spoke to Saria About Obtaining Fairy" }, { 0x01, "Spoke to Saria About Obtaining Fairy" },
{ 0x03, "Complained About Mido to Saria" }, { 0x03, "Complained About Mido to Saria" },
@ -331,7 +340,10 @@ const std::vector<FlagTable> flagTables = {
{ 0x1AF, "Entered Ganon's Castle (Collapsing)" }, { 0x1AF, "Entered Ganon's Castle (Collapsing)" },
{ 0x1D0, "No Sword on B" }, { 0x1D0, "No Sword on B" },
} }, } },
{ "Event Inf Flags", EVENT_INF, 0x03, { { "Event Inf Flags",
EVENT_INF,
0x03,
{
{ 0x00, "Rented Horse From Ingo" }, { 0x00, "Rented Horse From Ingo" },
{ 0x01, "Racing Ingo" }, { 0x01, "Racing Ingo" },
{ 0x02, "Won First Race With Ingo?" }, { 0x02, "Won First Race With Ingo?" },
@ -348,7 +360,10 @@ const std::vector<FlagTable> flagTables = {
{ 0x24, "Market Crowd Text Randomizer" }, { 0x24, "Market Crowd Text Randomizer" },
{ 0x30, "Entered the Market" }, { 0x30, "Entered the Market" },
} }, } },
{ "Randomizer Inf Flags", RANDOMIZER_INF, (RAND_INF_MAX + 15) / 16, { { "Randomizer Inf Flags",
RANDOMIZER_INF,
(RAND_INF_MAX + 15) / 16,
{
{ RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, "DUNGEONS_DONE_SPIRIT_TEMPLE" }, { RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, "DUNGEONS_DONE_SPIRIT_TEMPLE" },
{ RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, "DUNGEONS_DONE_SHADOW_TEMPLE" }, { RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, "DUNGEONS_DONE_SHADOW_TEMPLE" },
@ -363,14 +378,21 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_COWS_MILKED_GV_COW, "COWS_MILKED_GV_COW" }, { RAND_INF_COWS_MILKED_GV_COW, "COWS_MILKED_GV_COW" },
{ RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW, "COWS_MILKED_JABU_JABUS_BELLY_MQ_COW" }, { RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW, "COWS_MILKED_JABU_JABUS_BELLY_MQ_COW" },
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, "SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT" }, { RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT,
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, "SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS" }, "SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT" },
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, "SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT" }, { RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS,
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, "SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY" }, "SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS" },
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT,
"SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT" },
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY,
"SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY" },
{ RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB, "SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB" }, { RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB, "SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, "SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT" }, { RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT,
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, "SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT" }, "SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT, "SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT" }, { RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT,
"SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT,
"SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT, "SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT" }, { RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT, "SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT" },
{ RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO, "SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO" }, { RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO, "SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO" },
{ RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR, "SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR" }, { RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR, "SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR" },
@ -393,22 +415,35 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT, "SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT" }, { RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT, "SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT" },
{ RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT, "SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT" }, { RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT, "SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT" },
{ RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER, "SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER" }, { RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER, "SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER" },
{ RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, "SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR" }, { RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR,
{ RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, "SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT" }, "SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR" },
{ RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, "SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT" }, { RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT,
{ RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, "SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT" }, "SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT" },
{ RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT,
"SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT" },
{ RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT,
"SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT" },
{ RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE, "SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE" }, { RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE, "SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE" },
{ RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB, "SCRUBS_PURCHASED_DMC_DEKU_SCRUB" }, { RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB, "SCRUBS_PURCHASED_DMC_DEKU_SCRUB" },
{ RAND_INF_SCRUBS_PURCHASED_DEKU_TREE_MQ_DEKU_SCRUB, "SCRUBS_PURCHASED_DEKU_TREE_MQ_DEKU_SCRUB" }, { RAND_INF_SCRUBS_PURCHASED_DEKU_TREE_MQ_DEKU_SCRUB, "SCRUBS_PURCHASED_DEKU_TREE_MQ_DEKU_SCRUB" },
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, "SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR" }, { RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR,
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, "SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT" }, "SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR" },
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, "SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE" }, { RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT,
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, "SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS" }, "SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, "SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT" }, { RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE,
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, "SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT" }, "SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, "SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER" }, { RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS,
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, "SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT" }, "SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, "SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT" }, { RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT,
"SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT,
"SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER,
"SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT,
"SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT" },
{ RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT,
"SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT" },
{ RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1, "SHOP_ITEMS_KF_SHOP_ITEM_1" }, { RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1, "SHOP_ITEMS_KF_SHOP_ITEM_1" },
{ RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_2, "SHOP_ITEMS_KF_SHOP_ITEM_2" }, { RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_2, "SHOP_ITEMS_KF_SHOP_ITEM_2" },
@ -1048,10 +1083,14 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_3, "RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_3" }, { RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_3, "RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_3" },
{ RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_4, "RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_4" }, { RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_4, "RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_4" },
{ RAND_INF_WATER_TEMPLE_MQ_BOSS_KEY_POT, "RAND_INF_WATER_TEMPLE_MQ_BOSS_KEY_POT" }, { RAND_INF_WATER_TEMPLE_MQ_BOSS_KEY_POT, "RAND_INF_WATER_TEMPLE_MQ_BOSS_KEY_POT" },
{ RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_1, "RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_1" }, { RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_1,
{ RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_2, "RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_2" }, "RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_1" },
{ RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_1, "RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_1" }, { RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_2,
{ RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_2, "RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_2" }, "RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_2" },
{ RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_1,
"RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_1" },
{ RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_2,
"RAND_INF_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_2" },
{ RAND_INF_CAUGHT_LOACH, "RAND_INF_CAUGHT_LOACH" }, { RAND_INF_CAUGHT_LOACH, "RAND_INF_CAUGHT_LOACH" },
@ -1265,7 +1304,8 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_DEKU_TREE_BEFORE_BOSS_RIGHT_HEART, "RAND_INF_DEKU_TREE_BEFORE_BOSS_RIGHT_HEART" }, { RAND_INF_DEKU_TREE_BEFORE_BOSS_RIGHT_HEART, "RAND_INF_DEKU_TREE_BEFORE_BOSS_RIGHT_HEART" },
{ RAND_INF_DODONGOS_CAVERN_BLADE_ROOM_HEART, "RAND_INF_DODONGOS_CAVERN_BLADE_ROOM_HEART" }, { RAND_INF_DODONGOS_CAVERN_BLADE_ROOM_HEART, "RAND_INF_DODONGOS_CAVERN_BLADE_ROOM_HEART" },
{ RAND_INF_DODONGOS_CAVERN_UPPER_LIZALFOS_LEFT_HEART, "RAND_INF_DODONGOS_CAVERN_UPPER_LIZALFOS_LEFT_HEART" }, { RAND_INF_DODONGOS_CAVERN_UPPER_LIZALFOS_LEFT_HEART, "RAND_INF_DODONGOS_CAVERN_UPPER_LIZALFOS_LEFT_HEART" },
{ RAND_INF_DODONGOS_CAVERN_UPPER_LIZALFOS_RIGHT_HEART, "RAND_INF_DODONGOS_CAVERN_UPPER_LIZALFOS_RIGHT_HEART" }, { RAND_INF_DODONGOS_CAVERN_UPPER_LIZALFOS_RIGHT_HEART,
"RAND_INF_DODONGOS_CAVERN_UPPER_LIZALFOS_RIGHT_HEART" },
{ RAND_INF_FOREST_TEMPLE_COURTYARD_RIGHT_HEART, "RAND_INF_FOREST_TEMPLE_COURTYARD_RIGHT_HEART" }, { RAND_INF_FOREST_TEMPLE_COURTYARD_RIGHT_HEART, "RAND_INF_FOREST_TEMPLE_COURTYARD_RIGHT_HEART" },
{ RAND_INF_FOREST_TEMPLE_COURTYARD_LEFT_HEART, "RAND_INF_FOREST_TEMPLE_COURTYARD_LEFT_HEART" }, { RAND_INF_FOREST_TEMPLE_COURTYARD_LEFT_HEART, "RAND_INF_FOREST_TEMPLE_COURTYARD_LEFT_HEART" },
{ RAND_INF_FOREST_TEMPLE_WELL_WEST_HEART, "RAND_INF_FOREST_TEMPLE_WELL_WEST_HEART" }, { RAND_INF_FOREST_TEMPLE_WELL_WEST_HEART, "RAND_INF_FOREST_TEMPLE_WELL_WEST_HEART" },
@ -1284,11 +1324,13 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_WATER_TEMPLE_RIVER_HEART_3, "RAND_INF_WATER_TEMPLE_RIVER_HEART_3" }, { RAND_INF_WATER_TEMPLE_RIVER_HEART_3, "RAND_INF_WATER_TEMPLE_RIVER_HEART_3" },
{ RAND_INF_WATER_TEMPLE_RIVER_HEART_4, "RAND_INF_WATER_TEMPLE_RIVER_HEART_4" }, { RAND_INF_WATER_TEMPLE_RIVER_HEART_4, "RAND_INF_WATER_TEMPLE_RIVER_HEART_4" },
{ RAND_INF_SHADOW_TEMPLE_INVISIBLE_BLADES_LEFT_HEART, "RAND_INF_SHADOW_TEMPLE_INVISIBLE_BLADES_LEFT_HEART" }, { RAND_INF_SHADOW_TEMPLE_INVISIBLE_BLADES_LEFT_HEART, "RAND_INF_SHADOW_TEMPLE_INVISIBLE_BLADES_LEFT_HEART" },
{ RAND_INF_SHADOW_TEMPLE_INVISIBLE_BLADES_RIGHT_HEART, "RAND_INF_SHADOW_TEMPLE_INVISIBLE_BLADES_RIGHT_HEART" }, { RAND_INF_SHADOW_TEMPLE_INVISIBLE_BLADES_RIGHT_HEART,
"RAND_INF_SHADOW_TEMPLE_INVISIBLE_BLADES_RIGHT_HEART" },
{ RAND_INF_SHADOW_TEMPLE_SCARECROW_NORTH_HEART, "RAND_INF_SHADOW_TEMPLE_SCARECROW_NORTH_HEART" }, { RAND_INF_SHADOW_TEMPLE_SCARECROW_NORTH_HEART, "RAND_INF_SHADOW_TEMPLE_SCARECROW_NORTH_HEART" },
{ RAND_INF_SHADOW_TEMPLE_SCARECROW_SOUTH_HEART, "RAND_INF_SHADOW_TEMPLE_SCARECROW_SOUTH_HEART" }, { RAND_INF_SHADOW_TEMPLE_SCARECROW_SOUTH_HEART, "RAND_INF_SHADOW_TEMPLE_SCARECROW_SOUTH_HEART" },
{ RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_UPPER_LEFT_HEART, "RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_UPPER_LEFT_HEART" }, { RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_UPPER_LEFT_HEART, "RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_UPPER_LEFT_HEART" },
{ RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_UPPER_RIGHT_HEART, "RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_UPPER_RIGHT_HEART" }, { RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_UPPER_RIGHT_HEART,
"RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_UPPER_RIGHT_HEART" },
{ RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_LOWER_HEART, "RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_LOWER_HEART" }, { RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_LOWER_HEART, "RAND_INF_SHADOW_TEMPLE_AFTER_SHIP_LOWER_HEART" },
{ RAND_INF_ICE_CAVERN_LOBBY_RUPEE, "RAND_INF_ICE_CAVERN_LOBBY_RUPEE" }, { RAND_INF_ICE_CAVERN_LOBBY_RUPEE, "RAND_INF_ICE_CAVERN_LOBBY_RUPEE" },
{ RAND_INF_ICE_CAVERN_MAP_ROOM_LEFT_HEART, "RAND_INF_ICE_CAVERN_MAP_ROOM_LEFT_HEART" }, { RAND_INF_ICE_CAVERN_MAP_ROOM_LEFT_HEART, "RAND_INF_ICE_CAVERN_MAP_ROOM_LEFT_HEART" },
@ -1297,7 +1339,8 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1, "RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1" }, { RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1, "RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1" },
{ RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2, "RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2" }, { RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2, "RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2" },
{ RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3, "RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3" }, { RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3, "RAND_INF_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3" },
{ RAND_INF_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART, "RAND_INF_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART" }, { RAND_INF_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART,
"RAND_INF_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART" },
{ RAND_INF_GERUDO_TRAINING_GROUND_BEAMOS_SOUTH_HEART, "RAND_INF_GERUDO_TRAINING_GROUND_BEAMOS_SOUTH_HEART" }, { RAND_INF_GERUDO_TRAINING_GROUND_BEAMOS_SOUTH_HEART, "RAND_INF_GERUDO_TRAINING_GROUND_BEAMOS_SOUTH_HEART" },
{ RAND_INF_GERUDO_TRAINING_GROUND_BEAMOS_EAST_HEART, "RAND_INF_GERUDO_TRAINING_GROUND_BEAMOS_EAST_HEART" }, { RAND_INF_GERUDO_TRAINING_GROUND_BEAMOS_EAST_HEART, "RAND_INF_GERUDO_TRAINING_GROUND_BEAMOS_EAST_HEART" },
{ RAND_INF_GANONS_CASTLE_SHADOW_TRIAL_HEART_1, "RAND_INF_GANONS_CASTLE_SHADOW_TRIAL_HEART_1" }, { RAND_INF_GANONS_CASTLE_SHADOW_TRIAL_HEART_1, "RAND_INF_GANONS_CASTLE_SHADOW_TRIAL_HEART_1" },
@ -1312,7 +1355,8 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_LEFT_HEART, "RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_LEFT_HEART" }, { RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_LEFT_HEART, "RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_LEFT_HEART" },
{ RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_MIDDLE_HEART, "RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_MIDDLE_HEART" }, { RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_MIDDLE_HEART, "RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_MIDDLE_HEART" },
{ RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_RIGHT_HEART, "RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_RIGHT_HEART" }, { RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_RIGHT_HEART, "RAND_INF_DEKU_TREE_MQ_BEFORE_BOSS_RIGHT_HEART" },
{ RAND_INF_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_HEART, "RAND_INF_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_HEART" }, { RAND_INF_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_HEART,
"RAND_INF_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_HEART" },
{ RAND_INF_JABU_JABUS_BELLY_MQ_LIFT_HEART_1, "RAND_INF_JABU_JABUS_BELLY_MQ_LIFT_HEART_1" }, { RAND_INF_JABU_JABUS_BELLY_MQ_LIFT_HEART_1, "RAND_INF_JABU_JABUS_BELLY_MQ_LIFT_HEART_1" },
{ RAND_INF_JABU_JABUS_BELLY_MQ_LIFT_HEART_2, "RAND_INF_JABU_JABUS_BELLY_MQ_LIFT_HEART_2" }, { RAND_INF_JABU_JABUS_BELLY_MQ_LIFT_HEART_2, "RAND_INF_JABU_JABUS_BELLY_MQ_LIFT_HEART_2" },
{ RAND_INF_FOREST_TEMPLE_MQ_COURTYARD_RIGHT_HEART, "RAND_INF_FOREST_TEMPLE_MQ_COURTYARD_RIGHT_HEART" }, { RAND_INF_FOREST_TEMPLE_MQ_COURTYARD_RIGHT_HEART, "RAND_INF_FOREST_TEMPLE_MQ_COURTYARD_RIGHT_HEART" },
@ -1324,20 +1368,29 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_LEFT_HEART, "RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_LEFT_HEART" }, { RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_LEFT_HEART, "RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_LEFT_HEART" },
{ RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_RIGHT_HEART, "RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_RIGHT_HEART" }, { RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_RIGHT_HEART, "RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_RIGHT_HEART" },
{ RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_LOWER_HEART, "RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_LOWER_HEART" }, { RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_LOWER_HEART, "RAND_INF_FIRE_TEMPLE_MQ_FIRE_PILLAR_LOWER_HEART" },
{ RAND_INF_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_LEFT_HEART, "RAND_INF_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_LEFT_HEART" }, { RAND_INF_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_LEFT_HEART,
{ RAND_INF_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_RIGHT_HEART, "RAND_INF_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_RIGHT_HEART" }, "RAND_INF_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_LEFT_HEART" },
{ RAND_INF_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_RIGHT_HEART,
"RAND_INF_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_RIGHT_HEART" },
{ RAND_INF_SHADOW_TEMPLE_MQ_SCARECROW_NORTH_HEART, "RAND_INF_SHADOW_TEMPLE_MQ_SCARECROW_NORTH_HEART" }, { RAND_INF_SHADOW_TEMPLE_MQ_SCARECROW_NORTH_HEART, "RAND_INF_SHADOW_TEMPLE_MQ_SCARECROW_NORTH_HEART" },
{ RAND_INF_SHADOW_TEMPLE_MQ_SCARECROW_SOUTH_HEART, "RAND_INF_SHADOW_TEMPLE_MQ_SCARECROW_SOUTH_HEART" }, { RAND_INF_SHADOW_TEMPLE_MQ_SCARECROW_SOUTH_HEART, "RAND_INF_SHADOW_TEMPLE_MQ_SCARECROW_SOUTH_HEART" },
{ RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_UPPER_LEFT_HEART, "RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_UPPER_LEFT_HEART" }, { RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_UPPER_LEFT_HEART,
{ RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_UPPER_RIGHT_HEART, "RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_UPPER_RIGHT_HEART" }, "RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_UPPER_LEFT_HEART" },
{ RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_UPPER_RIGHT_HEART,
"RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_UPPER_RIGHT_HEART" },
{ RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_LOWER_HEART, "RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_LOWER_HEART" }, { RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_LOWER_HEART, "RAND_INF_SHADOW_TEMPLE_MQ_AFTER_SHIP_LOWER_HEART" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_FRONT_RIGHT_HEART, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_FRONT_RIGHT_HEART" }, { RAND_INF_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_FRONT_RIGHT_HEART,
"RAND_INF_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_FRONT_RIGHT_HEART" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_BOMB_LEFT_HEART, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_BOMB_LEFT_HEART" }, { RAND_INF_BOTTOM_OF_THE_WELL_MQ_BOMB_LEFT_HEART, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_BOMB_LEFT_HEART" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_BOMB_RIGHT_HEART, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_BOMB_RIGHT_HEART" }, { RAND_INF_BOTTOM_OF_THE_WELL_MQ_BOMB_RIGHT_HEART, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_BOMB_RIGHT_HEART" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_MIDDLE_LEFT_HEART, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_MIDDLE_LEFT_HEART" }, { RAND_INF_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_MIDDLE_LEFT_HEART,
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_FRONT_HEART, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_FRONT_HEART" }, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_MIDDLE_LEFT_HEART" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_LEFT_HEART, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_LEFT_HEART" }, { RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_FRONT_HEART,
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_RIGHT_HEART, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_RIGHT_HEART" }, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_FRONT_HEART" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_LEFT_HEART,
"RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_LEFT_HEART" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_RIGHT_HEART,
"RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_HALLWAY_RIGHT_HEART" },
{ RAND_INF_GANONS_CASTLE_MQ_WATER_TRIAL_HEART, "RAND_INF_GANONS_CASTLE_MQ_WATER_TRIAL_HEART" }, { RAND_INF_GANONS_CASTLE_MQ_WATER_TRIAL_HEART, "RAND_INF_GANONS_CASTLE_MQ_WATER_TRIAL_HEART" },
{ RAND_INF_GANONS_CASTLE_MQ_LIGHT_TRIAL_RIGHT_HEART, "RAND_INF_GANONS_CASTLE_MQ_LIGHT_TRIAL_RIGHT_HEART" }, { RAND_INF_GANONS_CASTLE_MQ_LIGHT_TRIAL_RIGHT_HEART, "RAND_INF_GANONS_CASTLE_MQ_LIGHT_TRIAL_RIGHT_HEART" },
{ RAND_INF_GANONS_CASTLE_MQ_LIGHT_TRIAL_LEFT_HEART, "RAND_INF_GANONS_CASTLE_MQ_LIGHT_TRIAL_LEFT_HEART" }, { RAND_INF_GANONS_CASTLE_MQ_LIGHT_TRIAL_LEFT_HEART, "RAND_INF_GANONS_CASTLE_MQ_LIGHT_TRIAL_LEFT_HEART" },
@ -1513,17 +1566,21 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY" }, { RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY" },
{ RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG" }, { RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_HF_COW_GROTTO_GOSSIP_STONE_FAIRY_BIG" },
{ RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY" }, { RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY" },
{ RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG" }, { RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG,
"RAND_INF_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG" },
{ RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY" }, { RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY" },
{ RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG" }, { RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG,
"RAND_INF_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG" },
{ RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY" }, { RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY" },
{ RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG" }, { RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG" },
{ RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY" }, { RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY" },
{ RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG" }, { RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG" },
{ RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY" }, { RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY" },
{ RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG" }, { RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG" },
{ RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY" }, { RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY,
{ RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG" }, "RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY" },
{ RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG,
"RAND_INF_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG" },
{ RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY" }, { RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY" },
{ RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG" }, { RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, "RAND_INF_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG" },
{ RAND_INF_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY" }, { RAND_INF_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY, "RAND_INF_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY" },
@ -1541,12 +1598,14 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, "RAND_INF_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY" }, { RAND_INF_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, "RAND_INF_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY" },
{ RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, "RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY" }, { RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, "RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY" },
{ RAND_INF_ICE_CAVERN_ENTRANCE_STORMS_FAIRY, "RAND_INF_ICE_CAVERN_ENTRANCE_STORMS_FAIRY" }, { RAND_INF_ICE_CAVERN_ENTRANCE_STORMS_FAIRY, "RAND_INF_ICE_CAVERN_ENTRANCE_STORMS_FAIRY" },
{ RAND_INF_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY, "RAND_INF_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY" }, { RAND_INF_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY,
"RAND_INF_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY" },
{ RAND_INF_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY, "RAND_INF_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY" }, { RAND_INF_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY, "RAND_INF_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY" },
{ RAND_INF_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY, "RAND_INF_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY" }, { RAND_INF_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY, "RAND_INF_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY" },
{ RAND_INF_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY, "RAND_INF_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY" }, { RAND_INF_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY, "RAND_INF_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY" },
{ RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY, "RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY" }, { RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY, "RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY" },
{ RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY, "RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY" }, { RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY,
"RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_LEFT_STORM_FAIRY" },
{ RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY, "RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY" }, { RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY, "RAND_INF_WATER_TEMPLE_MQ_DARK_LINK_RIGHT_SUN_FAIRY" },
{ RAND_INF_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, "RAND_INF_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY" }, { RAND_INF_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, "RAND_INF_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY" },
{ RAND_INF_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY, "RAND_INF_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY" }, { RAND_INF_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY, "RAND_INF_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY" },

View file

@ -66,7 +66,8 @@ std::map<int, std::string> cmdMap = {
}; };
void PerformDisplayListSearch() { void PerformDisplayListSearch() {
auto result = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*" + std::string(searchString) + "*DL*"); auto result = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles(
"*" + std::string(searchString) + "*DL*");
displayListSearchResults.clear(); displayListSearchResults.clear();
@ -79,14 +80,11 @@ void PerformDisplayListSearch() {
} }
// Sort the final list // Sort the final list
std::sort(displayListSearchResults.begin(), displayListSearchResults.end(), [](const std::string& a, const std::string& b) { std::sort(displayListSearchResults.begin(), displayListSearchResults.end(),
return std::lexicographical_compare( [](const std::string& a, const std::string& b) {
a.begin(), a.end(), return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), [](char c1, char c2) {
b.begin(), b.end(),
[](char c1, char c2) {
return std::tolower(c1) < std::tolower(c2); return std::tolower(c1) < std::tolower(c2);
} });
);
}); });
} }
@ -128,7 +126,8 @@ void DLViewerWindow::DrawElement() {
} }
try { try {
auto res = std::static_pointer_cast<Fast::DisplayList>(Ship::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList)); auto res = std::static_pointer_cast<Fast::DisplayList>(
Ship::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList));
if (res->GetInitData()->Type != static_cast<uint32_t>(Fast::ResourceType::DisplayList)) { if (res->GetInitData()->Type != static_cast<uint32_t>(Fast::ResourceType::DisplayList)) {
ImGui::Text("Resource type is not a Display List. Please choose another."); ImGui::Text("Resource type is not a Display List. Please choose another.");
@ -141,7 +140,8 @@ void DLViewerWindow::DrawElement() {
std::string id = "##CMD" + std::to_string(i); std::string id = "##CMD" + std::to_string(i);
Gfx* gfx = (Gfx*)&res->Instructions[i]; Gfx* gfx = (Gfx*)&res->Instructions[i];
int cmd = gfx->words.w0 >> 24; int cmd = gfx->words.w0 >> 24;
if (cmdMap.find(cmd) == cmdMap.end()) continue; if (cmdMap.find(cmd) == cmdMap.end())
continue;
std::string cmdLabel = cmdMap.at(cmd); std::string cmdLabel = cmdMap.at(cmd);
@ -199,8 +199,7 @@ void DLViewerWindow::DrawElement() {
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();
} }
if (cmd == G_RDPPIPESYNC) { if (cmd == G_RDPPIPESYNC) {}
}
if (cmd == G_SETGRAYSCALE) { if (cmd == G_SETGRAYSCALE) {
bool* state = (bool*)&gfx->words.w1; bool* state = (bool*)&gfx->words.w1;
ImGui::SameLine(); ImGui::SameLine();
@ -304,8 +303,7 @@ void DLViewerWindow::DrawElement() {
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text("Vertex Name: %s", fileName); ImGui::Text("Vertex Name: %s", fileName);
} }
if (cmd == G_DL) { if (cmd == G_DL) {}
}
if (cmd == G_DL_OTR_HASH) { if (cmd == G_DL_OTR_HASH) {
gfx++; gfx++;
uint64_t hash = ((uint64_t)gfx->words.w0 << 32) + (uint64_t)gfx->words.w1; uint64_t hash = ((uint64_t)gfx->words.w0 << 32) + (uint64_t)gfx->words.w1;
@ -320,8 +318,8 @@ void DLViewerWindow::DrawElement() {
} }
// Skip second half of instructions that are over 128-bit wide // Skip second half of instructions that are over 128-bit wide
if (cmd == G_SETTIMG_OTR_HASH || cmd == G_DL_OTR_HASH || cmd == G_VTX_OTR_HASH || if (cmd == G_SETTIMG_OTR_HASH || cmd == G_DL_OTR_HASH || cmd == G_VTX_OTR_HASH || cmd == G_BRANCH_Z_OTR ||
cmd == G_BRANCH_Z_OTR || cmd == G_MARKER || cmd == G_MTX_OTR) { cmd == G_MARKER || cmd == G_MTX_OTR) {
i++; i++;
ImGui::Text("%lu - Reserved - Second half of %s", i, cmdLabel.c_str()); ImGui::Text("%lu - Reserved - Second half of %s", i, cmdLabel.c_str());
} }

View file

@ -36,4 +36,3 @@ void ResetPerformanceTimer(TimerID timer);
void ResetPerformanceTimers(); void ResetPerformanceTimers();
static std::array<std::chrono::duration<double, std::milli>, PT_MAX> totalTimes = {}; static std::array<std::chrono::duration<double, std::milli>, PT_MAX> totalTimes = {};
static std::array<std::chrono::high_resolution_clock::time_point, PT_MAX> timeStarted = {}; static std::array<std::chrono::high_resolution_clock::time_point, PT_MAX> timeStarted = {};

View file

@ -77,27 +77,35 @@ std::vector<ValueTableElement> valueTable = {
extern "C" void ValueViewer_Draw(GfxPrint* printer) { extern "C" void ValueViewer_Draw(GfxPrint* printer) {
for (int i = 0; i < valueTable.size(); i++) { for (int i = 0; i < valueTable.size(); i++) {
ValueTableElement& element = valueTable[i]; ValueTableElement& element = valueTable[i];
if (!element.isActive || !element.isPrinted || (gPlayState == NULL && element.requiresPlayState)) continue; if (!element.isActive || !element.isPrinted || (gPlayState == NULL && element.requiresPlayState))
GfxPrint_SetColor(printer, element.color.x * 255, element.color.y * 255, element.color.z * 255, element.color.w * 255); continue;
GfxPrint_SetColor(printer, element.color.x * 255, element.color.y * 255, element.color.z * 255,
element.color.w * 255);
GfxPrint_SetPos(printer, element.x, element.y); GfxPrint_SetPos(printer, element.x, element.y);
switch (element.type) { switch (element.type) {
case TYPE_S8: case TYPE_S8:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s8*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(),
*(s8*)element.valueFn());
break; break;
case TYPE_U8: case TYPE_U8:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u8*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(),
*(u8*)element.valueFn());
break; break;
case TYPE_S16: case TYPE_S16:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s16*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(),
*(s16*)element.valueFn());
break; break;
case TYPE_U16: case TYPE_U16:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u16*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(),
*(u16*)element.valueFn());
break; break;
case TYPE_S32: case TYPE_S32:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s32*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(),
*(s32*)element.valueFn());
break; break;
case TYPE_U32: case TYPE_U32:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u32*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(),
*(u32*)element.valueFn());
break; break;
case TYPE_CHAR: case TYPE_CHAR:
GfxPrint_Printf(printer, "%s%c", element.prefix.c_str(), *(char*)element.valueFn()); GfxPrint_Printf(printer, "%s%c", element.prefix.c_str(), *(char*)element.valueFn());
@ -106,7 +114,8 @@ extern "C" void ValueViewer_Draw(GfxPrint* printer) {
GfxPrint_Printf(printer, "%s%s", element.prefix.c_str(), (char*)element.valueFn()); GfxPrint_Printf(printer, "%s%s", element.prefix.c_str(), (char*)element.valueFn());
break; break;
case TYPE_FLOAT: case TYPE_FLOAT:
GfxPrint_Printf(printer, (element.typeFormat ? "%s%4.1f" : "%s%f"), element.prefix.c_str(), *(float*)element.valueFn()); GfxPrint_Printf(printer, (element.typeFormat ? "%s%4.1f" : "%s%f"), element.prefix.c_str(),
*(float*)element.valueFn());
break; break;
} }
} }
@ -149,17 +158,16 @@ void ValueViewerWindow::DrawElement() {
ImGui::BeginGroup(); ImGui::BeginGroup();
static int selectedElement = -1; static int selectedElement = -1;
std::string selectedElementText = (selectedElement == -1) ? "Select a value" : ( std::string selectedElementText = (selectedElement == -1) ? "Select a value"
std::string(valueTable[selectedElement].name) + " (" + std::string(valueTable[selectedElement].path) + ")" : (std::string(valueTable[selectedElement].name) + " (" +
); std::string(valueTable[selectedElement].path) + ")");
UIWidgets::PushStyleCombobox(THEME_COLOR); UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##valueViewerElement", selectedElementText.c_str())) { if (ImGui::BeginCombo("##valueViewerElement", selectedElementText.c_str())) {
for (int i = 0; i < valueTable.size(); i++) { for (int i = 0; i < valueTable.size(); i++) {
if (valueTable[i].isActive) continue; if (valueTable[i].isActive)
continue;
bool isSelected = (selectedElement == i); bool isSelected = (selectedElement == i);
std::string elementText = ( std::string elementText = (std::string(valueTable[i].name) + " (" + std::string(valueTable[i].path) + ")");
std::string(valueTable[i].name) + " (" + std::string(valueTable[i].path) + ")"
);
if (ImGui::Selectable(elementText.c_str(), isSelected)) { if (ImGui::Selectable(elementText.c_str(), isSelected)) {
selectedElement = i; selectedElement = i;
} }
@ -181,7 +189,8 @@ void ValueViewerWindow::DrawElement() {
for (int i = 0; i < valueTable.size(); i++) { for (int i = 0; i < valueTable.size(); i++) {
ValueTableElement& element = valueTable[i]; ValueTableElement& element = valueTable[i];
if (!element.isActive || (gPlayState == NULL && element.requiresPlayState)) continue; if (!element.isActive || (gPlayState == NULL && element.requiresPlayState))
continue;
UIWidgets::PushStyleButton(THEME_COLOR); UIWidgets::PushStyleButton(THEME_COLOR);
UIWidgets::PushStyleCheckbox(THEME_COLOR); UIWidgets::PushStyleCheckbox(THEME_COLOR);
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
@ -249,7 +258,8 @@ void ValueViewerWindow::DrawElement() {
} }
UIWidgets::PopStyleInput(); UIWidgets::PopStyleInput();
ImGui::SameLine(); ImGui::SameLine();
ImGui::ColorEdit3(("##color" + std::string(element.name)).c_str(), (float*)&element.color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel); ImGui::ColorEdit3(("##color" + std::string(element.name)).c_str(), (float*)&element.color,
ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
ImGui::SameLine(); ImGui::SameLine();
UIWidgets::PushStyleCheckbox(THEME_COLOR); UIWidgets::PushStyleCheckbox(THEME_COLOR);
if (ImGui::Button(("Position##" + std::string(element.name)).c_str())) { if (ImGui::Button(("Position##" + std::string(element.name)).c_str())) {

View file

@ -42,18 +42,54 @@ const char* enemyCVarList[] = {
}; };
const char* enemyNameList[] = { const char* enemyNameList[] = {
"Armos", "Arwing", "Baby Dodongo", "Bari", "Armos",
"Beamos", "Big Skulltula", "Stalchild (Big)", "Biri", "Arwing",
"Iron Knuckle (Black)", "Blue Tektite", "Bubble", "Club Moblin", "Baby Dodongo",
"Dark Link", "Dinolfos", "Dodongo", "Fire Keese", "Bari",
"Floor Tile", "Floormaster", "Flying Peahat", "Flying Pot", "Beamos",
"Freezard", "Gibdo", "Gohma Larva", "Guay", "Big Skulltula",
"Ice Keese", "Invisible Skulltula", "Keese", "Large Deku Baba", "Stalchild (Big)",
"Like-Like", "Lizalfos", "Mad Scrub", "Wolfos (Normal)", "Biri",
"Peahat Larva", "Redead", "Red Tektite", "Shabom", "Iron Knuckle (Black)",
"Shell Blade", "Skulltula", "Small Deku Baba", "Stalchild (Small)", "Blue Tektite",
"Spike", "Stalfos", "Stinger", "Tailpasaran", "Bubble",
"Torch Slug", "Wallmaster", "Iron Knuckle (White)", "Wolfos (White)", "Club Moblin",
"Dark Link",
"Dinolfos",
"Dodongo",
"Fire Keese",
"Floor Tile",
"Floormaster",
"Flying Peahat",
"Flying Pot",
"Freezard",
"Gibdo",
"Gohma Larva",
"Guay",
"Ice Keese",
"Invisible Skulltula",
"Keese",
"Large Deku Baba",
"Like-Like",
"Lizalfos",
"Mad Scrub",
"Wolfos (Normal)",
"Peahat Larva",
"Redead",
"Red Tektite",
"Shabom",
"Shell Blade",
"Skulltula",
"Small Deku Baba",
"Stalchild (Small)",
"Spike",
"Stalfos",
"Stinger",
"Tailpasaran",
"Torch Slug",
"Wallmaster",
"Iron Knuckle (White)",
"Wolfos (White)",
"Withered Deku Baba", "Withered Deku Baba",
}; };
@ -111,9 +147,10 @@ static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] =
// Doesn't work {ACTOR_EN_POH, 0}, // Poe (Seems to rely on other objects?) // Doesn't work {ACTOR_EN_POH, 0}, // Poe (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_POH, 2}, // Poe (composer Sharp) (Seems to rely on other objects?) // Doesn't work {ACTOR_EN_POH, 2}, // Poe (composer Sharp) (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_POH, 3}, // Poe (composer Flat) (Seems to rely on other objects?) // Doesn't work {ACTOR_EN_POH, 3}, // Poe (composer Flat) (Seems to rely on other objects?)
// Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping up) // Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping
// Doesn't work {ACTOR_EN_REEBA, 0}, // Leever (reliant on surface and also normally used in tandem with a leever spawner, kills itself too quickly otherwise) // up) Doesn't work {ACTOR_EN_REEBA, 0}, // Leever (reliant on surface and also normally used in tandem with a
// Kinda doesn't work { ACTOR_EN_FD, 0 }, // Flare Dancer (jumps out of bounds a lot, and possible cause of crashes because of spawning a ton of flame actors) // leever spawner, kills itself too quickly otherwise) Kinda doesn't work { ACTOR_EN_FD, 0 }, // Flare Dancer (jumps
// out of bounds a lot, and possible cause of crashes because of spawning a ton of flame actors)
}; };
static int enemiesToRandomize[] = { static int enemiesToRandomize[] = {
@ -147,7 +184,8 @@ static int enemiesToRandomize[] = {
ACTOR_EN_FLOORMAS, // Floormaster ACTOR_EN_FLOORMAS, // Floormaster
ACTOR_EN_RD, // Redead, Gibdo ACTOR_EN_RD, // Redead, Gibdo
ACTOR_EN_SW, // Skullwalltula ACTOR_EN_SW, // Skullwalltula
// ACTOR_EN_FD, // Flare Dancer (can be randomized, but not randomized to, so keeping it in vanilla locations means it at least shows up in the game) // ACTOR_EN_FD, // Flare Dancer (can be randomized, but not randomized to, so keeping it in vanilla locations
// means it at least shows up in the game)
ACTOR_EN_SB, // Shell Blade ACTOR_EN_SB, // Shell Blade
ACTOR_EN_KAREBABA, // Withered Deku Baba ACTOR_EN_KAREBABA, // Withered Deku Baba
ACTOR_EN_RR, // Like-Like ACTOR_EN_RR, // Like-Like
@ -171,7 +209,8 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
// This should probably be handled on OTR generation in the future when object dependency is fully removed. // This should probably be handled on OTR generation in the future when object dependency is fully removed.
// Remove bats and Skulltulas from graveyard. // Remove bats and Skulltulas from graveyard.
// Remove Octorok in Lost Woods. // Remove Octorok in Lost Woods.
if (((*actorId == ACTOR_EN_FIREFLY || (*actorId == ACTOR_EN_SW && *params == 0)) && play->sceneNum == SCENE_GRAVEYARD) || if (((*actorId == ACTOR_EN_FIREFLY || (*actorId == ACTOR_EN_SW && *params == 0)) &&
play->sceneNum == SCENE_GRAVEYARD) ||
(*actorId == ACTOR_EN_OKUTA && play->sceneNum == SCENE_LOST_WOODS)) { (*actorId == ACTOR_EN_OKUTA && play->sceneNum == SCENE_LOST_WOODS)) {
return 0; return 0;
} }
@ -229,7 +268,8 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
} }
// Get randomized enemy ID and parameter. // Get randomized enemy ID and parameter.
uint32_t seed = play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params; uint32_t seed =
play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params;
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed); EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed);
int8_t timesRandomized = 1; int8_t timesRandomized = 1;
@ -305,7 +345,8 @@ EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
GetSelectedEnemies(); GetSelectedEnemies();
} }
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) { if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt); uint32_t finalSeed =
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed); Random_Init(finalSeed);
uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE); uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE);
return selectedEnemyList[randomNumber]; return selectedEnemyList[randomNumber];
@ -357,17 +398,19 @@ bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId,
// Don't randomize the Wolfos in SFM because it's needed to open the gate. // Don't randomize the Wolfos in SFM because it's needed to open the gate.
case ACTOR_EN_WF: case ACTOR_EN_WF:
return (params != 7936); return (params != 7936);
// Don't randomize the Stalfos in Forest Temple because other enemies fall through the hole and don't trigger the platform. // Don't randomize the Stalfos in Forest Temple because other enemies fall through the hole and don't
// Don't randomize the Stalfos spawning on the boat in Shadow Temple, as randomizing them places the new enemies // trigger the platform. Don't randomize the Stalfos spawning on the boat in Shadow Temple, as
// down in the river. // randomizing them places the new enemies down in the river.
case ACTOR_EN_TEST: case ACTOR_EN_TEST:
return (params != 1 && !(sceneNum == SCENE_SHADOW_TEMPLE && roomNum == 21)); return (params != 1 && !(sceneNum == SCENE_SHADOW_TEMPLE && roomNum == 21));
// Only randomize the enemy variant of Armos Statue. // Only randomize the enemy variant of Armos Statue.
// Leave one Armos unrandomized in the Spirit Temple room where an armos is needed to push down a button. // Leave one Armos unrandomized in the Spirit Temple room where an armos is needed to push down a
// button.
case ACTOR_EN_AM: case ACTOR_EN_AM:
return ((params == -1 || params == 255) && !(sceneNum == SCENE_SPIRIT_TEMPLE && posX == 2141)); return ((params == -1 || params == 255) && !(sceneNum == SCENE_SPIRIT_TEMPLE && posX == 2141));
// Don't randomize Shell Blades and Spikes in the underwater portion in Water Temple as it's impossible to kill // Don't randomize Shell Blades and Spikes in the underwater portion in Water Temple as it's impossible
// most other enemies underwater with just hookshot and they're required to be killed for a grate to open. // to kill most other enemies underwater with just hookshot and they're required to be killed for a
// grate to open.
case ACTOR_EN_SB: case ACTOR_EN_SB:
case ACTOR_EN_NY: case ACTOR_EN_NY:
return (!(!isMQ && sceneNum == SCENE_WATER_TEMPLE && roomNum == 2)); return (!(!isMQ && sceneNum == SCENE_WATER_TEMPLE && roomNum == 2));
@ -403,7 +446,8 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
// Deku Tree // Deku Tree
case SCENE_DEKU_TREE: case SCENE_DEKU_TREE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 9)) && return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 9)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 4 || roomNum == 6 || roomNum == 9 || roomNum == 10))); !(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 4 || roomNum == 6 || roomNum == 9 || roomNum == 10)));
// Dodongo's Cavern // Dodongo's Cavern
case SCENE_DODONGOS_CAVERN: case SCENE_DODONGOS_CAVERN:
return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) && return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) &&
@ -415,8 +459,10 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 11 || roomNum == 14))); !(isMQ && enemiesToExcludeClearRooms && (roomNum == 11 || roomNum == 14)));
// Forest Temple // Forest Temple
case SCENE_FOREST_TEMPLE: case SCENE_FOREST_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) && return (!(!isMQ && enemiesToExcludeClearRooms &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21))); (roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) &&
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21)));
// Fire Temple // Fire Temple
case SCENE_FIRE_TEMPLE: case SCENE_FIRE_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) && return (!(!isMQ && enemiesToExcludeClearRooms && roomNum == 15) &&
@ -427,23 +473,31 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18))); !(isMQ && enemiesToExcludeClearRooms && (roomNum == 13 || roomNum == 18)));
// Spirit Temple // Spirit Temple
case SCENE_SPIRIT_TEMPLE: case SCENE_SPIRIT_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 10 || roomNum == 17 || roomNum == 20)) && return (!(!isMQ && enemiesToExcludeClearRooms &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 2 || roomNum == 4 || roomNum == 10 || roomNum == 15 || roomNum == 19 || roomNum == 20))); (roomNum == 1 || roomNum == 10 || roomNum == 17 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 1 || roomNum == 2 || roomNum == 4 || roomNum == 10 || roomNum == 15 ||
roomNum == 19 || roomNum == 20)));
// Shadow Temple // Shadow Temple
case SCENE_SHADOW_TEMPLE: case SCENE_SHADOW_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && return (
(roomNum == 1 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 16 || roomNum == 17 || roomNum == 19 || roomNum == 20)) && !(!isMQ && enemiesToExcludeClearRooms &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 6 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 20))); (roomNum == 1 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 16 || roomNum == 17 ||
roomNum == 19 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 1 || roomNum == 6 || roomNum == 7 || roomNum == 11 || roomNum == 14 || roomNum == 20)));
// Ganon's Castle Trials // Ganon's Castle Trials
case SCENE_INSIDE_GANONS_CASTLE: case SCENE_INSIDE_GANONS_CASTLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 5 || roomNum == 9)) && return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 2 || roomNum == 5 || roomNum == 9)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 0 || roomNum == 2 || roomNum == 5 || roomNum == 9))); !(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 0 || roomNum == 2 || roomNum == 5 || roomNum == 9)));
// Ice Caverns // Ice Caverns
case SCENE_ICE_CAVERN: case SCENE_ICE_CAVERN:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 7)) && return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 7)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 7))); !(isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 7)));
// Bottom of the Well // Bottom of the Well
// Exclude Dark Link from room with holes in the floor because it can pull you in a like-like making the player fall down. // Exclude Dark Link from room with holes in the floor because it can pull you in a like-like making the player
// fall down.
case SCENE_BOTTOM_OF_THE_WELL: case SCENE_BOTTOM_OF_THE_WELL:
return (!(!isMQ && enemy.id == ACTOR_EN_TORCH2 && roomNum == 3)); return (!(!isMQ && enemy.id == ACTOR_EN_TORCH2 && roomNum == 3));
// Don't allow Dark Link in areas with lava void out zones as it voids out the player as well. // Don't allow Dark Link in areas with lava void out zones as it voids out the player as well.
@ -452,18 +506,21 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
return (!(enemy.id == ACTOR_EN_TORCH2 && roomNum == 6) && return (!(enemy.id == ACTOR_EN_TORCH2 && roomNum == 6) &&
!(!isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 7)) && !(!isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 7)) &&
!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 5 || roomNum == 10)) && !(!isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 5 || roomNum == 10)) &&
!(isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 3 || roomNum == 5 || roomNum == 7)) && !(isMQ && enemiesToExcludeTimedRooms &&
(roomNum == 1 || roomNum == 3 || roomNum == 5 || roomNum == 7)) &&
!(isMQ && enemiesToExcludeClearRooms && roomNum == 10)); !(isMQ && enemiesToExcludeClearRooms && roomNum == 10));
// Don't allow certain enemies in Ganon's Tower because they would spawn up on the ceiling, // Don't allow certain enemies in Ganon's Tower because they would spawn up on the ceiling,
// becoming impossible to kill. // becoming impossible to kill.
// Ganon's Tower. // Ganon's Tower.
case SCENE_GANONS_TOWER: case SCENE_GANONS_TOWER:
return (!(enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI || (enemy.id == ACTOR_EN_ZF && enemy.params == -1))); return (!(enemiesToExcludeClearRooms || enemy.id == ACTOR_EN_VALI ||
(enemy.id == ACTOR_EN_ZF && enemy.params == -1)));
// Ganon's Tower Escape. // Ganon's Tower Escape.
case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR: case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR:
return (!((enemiesToExcludeTimedRooms || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)) && roomNum == 1)); return (!((enemiesToExcludeTimedRooms || (enemy.id == ACTOR_EN_ZF && enemy.params == -1)) && roomNum == 1));
// Don't allow big Stalchildren, big Peahats and the large Bari (jellyfish) during the Gohma fight because they can clip into Gohma // Don't allow big Stalchildren, big Peahats and the large Bari (jellyfish) during the Gohma fight because they
// and it crashes the game. Likely because Gohma on the ceiling can't handle collision with other enemies. // can clip into Gohma and it crashes the game. Likely because Gohma on the ceiling can't handle collision with
// other enemies.
case SCENE_DEKU_TREE_BOSS: case SCENE_DEKU_TREE_BOSS:
return (!enemiesToExcludeTimedRooms && !(enemy.id == ACTOR_EN_SKB && enemy.params == 20) && return (!enemiesToExcludeTimedRooms && !(enemy.id == ACTOR_EN_SKB && enemy.params == 20) &&
!(enemy.id == ACTOR_EN_PEEHAT && enemy.params == -1)); !(enemy.id == ACTOR_EN_PEEHAT && enemy.params == -1));

View file

@ -18,5 +18,6 @@ extern const char* enemyNameList[];
extern void GetSelectedEnemies(); extern void GetSelectedEnemies();
#ifndef __cplusplus #ifndef __cplusplus
uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX, int16_t *rotY, int16_t *rotZ, int16_t *params); uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* posX, f32* posY, f32* posZ, int16_t* rotX,
int16_t* rotY, int16_t* rotZ, int16_t* params);
#endif #endif

View file

@ -100,10 +100,8 @@ namespace GameInteractionEffect {
GameInteractionEffectQueryResult ModifyHeartContainers::CanBeApplied() { GameInteractionEffectQueryResult ModifyHeartContainers::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if ( } else if ((parameters[0] > 0 && (gSaveContext.healthCapacity + (parameters[0] * 0x10) > 0x140)) ||
(parameters[0] > 0 && (gSaveContext.healthCapacity + (parameters[0] * 0x10) > 0x140)) || (parameters[0] < 0 && (gSaveContext.healthCapacity + (parameters[0] * 0x10) < 0x10))) {
(parameters[0] < 0 && (gSaveContext.healthCapacity + (parameters[0] * 0x10) < 0x10))
) {
return GameInteractionEffectQueryResult::NotPossible; return GameInteractionEffectQueryResult::NotPossible;
} }
@ -146,10 +144,8 @@ namespace GameInteractionEffect {
GameInteractionEffectQueryResult ModifyRupees::CanBeApplied() { GameInteractionEffectQueryResult ModifyRupees::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if ( } else if ((parameters[0] < 0 && gSaveContext.rupees <= 0) ||
(parameters[0] < 0 && gSaveContext.rupees <= 0) || (parameters[0] > 0 && gSaveContext.rupees >= CUR_CAPACITY(UPG_WALLET))) {
(parameters[0] > 0 && gSaveContext.rupees >= CUR_CAPACITY(UPG_WALLET))
) {
return GameInteractionEffectQueryResult::NotPossible; return GameInteractionEffectQueryResult::NotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
@ -193,10 +189,8 @@ namespace GameInteractionEffect {
GameInteractionEffectQueryResult ModifyHealth::CanBeApplied() { GameInteractionEffectQueryResult ModifyHealth::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if ( } else if ((parameters[0] > 0 && gSaveContext.health == gSaveContext.healthCapacity) ||
(parameters[0] > 0 && gSaveContext.health == gSaveContext.healthCapacity) (parameters[0] < 0 && (gSaveContext.health + (16 * parameters[0]) <= 0))) {
|| (parameters[0] < 0 && (gSaveContext.health + (16 * parameters[0]) <= 0))
) {
return GameInteractionEffectQueryResult::NotPossible; return GameInteractionEffectQueryResult::NotPossible;
} }
@ -261,7 +255,8 @@ namespace GameInteractionEffect {
// MARK: - KnockbackPlayer // MARK: - KnockbackPlayer
GameInteractionEffectQueryResult KnockbackPlayer::CanBeApplied() { GameInteractionEffectQueryResult KnockbackPlayer::CanBeApplied() {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || player->stateFlags2 & PLAYER_STATE2_CRAWLING) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() ||
player->stateFlags2 & PLAYER_STATE2_CRAWLING) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
@ -427,7 +422,8 @@ namespace GameInteractionEffect {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if ((parameters[0] > 0 && ((gBitFlags[parameters[0] - ITEM_SHIELD_DEKU] << gEquipShifts[EQUIP_TYPE_SHIELD]) & } else if ((parameters[0] > 0 && ((gBitFlags[parameters[0] - ITEM_SHIELD_DEKU] << gEquipShifts[EQUIP_TYPE_SHIELD]) &
gSaveContext.inventory.equipment)) || gSaveContext.inventory.equipment)) ||
(parameters[0] < 0 && !((gBitFlags[(parameters[0] * -1) - ITEM_SHIELD_DEKU] << gEquipShifts[EQUIP_TYPE_SHIELD]) & (parameters[0] < 0 &&
!((gBitFlags[(parameters[0] * -1) - ITEM_SHIELD_DEKU] << gEquipShifts[EQUIP_TYPE_SHIELD]) &
gSaveContext.inventory.equipment))) { gSaveContext.inventory.equipment))) {
return GameInteractionEffectQueryResult::NotPossible; return GameInteractionEffectQueryResult::NotPossible;
} else { } else {
@ -664,4 +660,4 @@ namespace GameInteractionEffect {
void SpawnActor::_Apply() { void SpawnActor::_Apply() {
GameInteractor::RawAction::SpawnActor(parameters[0], parameters[1]); GameInteractor::RawAction::SpawnActor(parameters[0], parameters[1]);
} }
} } // namespace GameInteractionEffect

View file

@ -6,16 +6,13 @@
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus
enum GameInteractionEffectQueryResult { enum GameInteractionEffectQueryResult { Possible = 0x00, TemporarilyNotPossible = 0x01, NotPossible = 0xFF };
Possible = 0x00,
TemporarilyNotPossible = 0x01,
NotPossible = 0xFF
};
class GameInteractionEffectBase { class GameInteractionEffectBase {
public: public:
virtual GameInteractionEffectQueryResult CanBeApplied() = 0; virtual GameInteractionEffectQueryResult CanBeApplied() = 0;
GameInteractionEffectQueryResult Apply(); GameInteractionEffectQueryResult Apply();
protected: protected:
virtual void _Apply() = 0; virtual void _Apply() = 0;
}; };
@ -24,6 +21,7 @@ class RemovableGameInteractionEffect: public GameInteractionEffectBase {
public: public:
virtual GameInteractionEffectQueryResult CanBeRemoved(); virtual GameInteractionEffectQueryResult CanBeRemoved();
GameInteractionEffectQueryResult Remove(); GameInteractionEffectQueryResult Remove();
protected: protected:
virtual void _Remove(){}; virtual void _Remove(){};
}; };
@ -270,7 +268,7 @@ namespace GameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
} } // namespace GameInteractionEffect
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif /* GameInteractionEffect_h */ #endif /* GameInteractionEffect_h */

View file

@ -54,7 +54,10 @@ bool GameInteractor::IsSaveLoaded(bool allowDbgSave) {
bool GameInteractor::IsGameplayPaused() { bool GameInteractor::IsGameplayPaused() {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
return (Player_InBlockingCsMode(gPlayState, player) || gPlayState->pauseCtx.state != 0 || gPlayState->msgCtx.msgMode != 0) ? true : false; return (Player_InBlockingCsMode(gPlayState, player) || gPlayState->pauseCtx.state != 0 ||
gPlayState->msgCtx.msgMode != 0)
? true
: false;
} }
bool GameInteractor::CanSpawnActor() { bool GameInteractor::CanSpawnActor() {

View file

@ -266,7 +266,8 @@ void GameInteractor_ExecuteOnUpdateFileQuestSelection(uint8_t questIndex) {
} }
void GameInteractor_ExecuteOnUpdateFileBossRushOptionSelection(uint8_t optionIndex, uint8_t optionValue) { void GameInteractor_ExecuteOnUpdateFileBossRushOptionSelection(uint8_t optionIndex, uint8_t optionValue) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnUpdateFileBossRushOptionSelection>(optionIndex, optionValue); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnUpdateFileBossRushOptionSelection>(optionIndex,
optionValue);
} }
void GameInteractor_ExecuteOnUpdateFileNameSelection(int16_t charCode) { void GameInteractor_ExecuteOnUpdateFileNameSelection(int16_t charCode) {

View file

@ -143,11 +143,13 @@ void GameInteractor::RawAction::SetSceneFlag(int16_t sceneNum, int16_t flagType,
} }
break; break;
case FlagType::FLAG_SCENE_CLEAR: case FlagType::FLAG_SCENE_CLEAR:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.clear |= (1 << flag); if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.clear |= (1 << flag);
gSaveContext.sceneFlags[sceneNum].clear |= (1 << flag); gSaveContext.sceneFlags[sceneNum].clear |= (1 << flag);
break; break;
case FlagType::FLAG_SCENE_TREASURE: case FlagType::FLAG_SCENE_TREASURE:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.chest |= (1 << flag); if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.chest |= (1 << flag);
gSaveContext.sceneFlags[sceneNum].chest |= (1 << flag); gSaveContext.sceneFlags[sceneNum].chest |= (1 << flag);
break; break;
case FlagType::FLAG_SCENE_COLLECTIBLE: case FlagType::FLAG_SCENE_COLLECTIBLE:
@ -182,11 +184,13 @@ void GameInteractor::RawAction::UnsetSceneFlag(int16_t sceneNum, int16_t flagTyp
} }
break; break;
case FlagType::FLAG_SCENE_CLEAR: case FlagType::FLAG_SCENE_CLEAR:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.clear &= ~(1 << flag); if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.clear &= ~(1 << flag);
gSaveContext.sceneFlags[sceneNum].clear &= ~(1 << flag); gSaveContext.sceneFlags[sceneNum].clear &= ~(1 << flag);
break; break;
case FlagType::FLAG_SCENE_TREASURE: case FlagType::FLAG_SCENE_TREASURE:
if (sceneNum == gPlayState->sceneNum) gPlayState->actorCtx.flags.chest &= ~(1 << flag); if (sceneNum == gPlayState->sceneNum)
gPlayState->actorCtx.flags.chest &= ~(1 << flag);
gSaveContext.sceneFlags[sceneNum].chest &= ~(1 << flag); gSaveContext.sceneFlags[sceneNum].chest &= ~(1 << flag);
break; break;
case FlagType::FLAG_SCENE_COLLECTIBLE: case FlagType::FLAG_SCENE_COLLECTIBLE:
@ -355,7 +359,8 @@ void GameInteractor::RawAction::UpdateActor(void* refActor) {
} }
void GameInteractor::RawAction::TeleportPlayer(int32_t nextEntrance) { void GameInteractor::RawAction::TeleportPlayer(int32_t nextEntrance) {
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
gPlayState->nextEntranceIndex = nextEntrance; gPlayState->nextEntranceIndex = nextEntrance;
gPlayState->transitionTrigger = TRANS_TRIGGER_START; gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK; gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;
@ -496,18 +501,12 @@ void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint
void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) { void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) {
const char* cvarsToLock[12] = { const char* cvarsToLock[12] = {
CVAR_COSMETIC("Link.KokiriTunic.Locked"), CVAR_COSMETIC("Link.KokiriTunic.Locked"), CVAR_COSMETIC("Link.GoronTunic.Locked"),
CVAR_COSMETIC("Link.GoronTunic.Locked"), CVAR_COSMETIC("Link.ZoraTunic.Locked"), CVAR_COSMETIC("Navi.EnemyPrimary.Locked"),
CVAR_COSMETIC("Link.ZoraTunic.Locked"), CVAR_COSMETIC("Navi.EnemySecondary.Locked"), CVAR_COSMETIC("Navi.IdlePrimary.Locked"),
CVAR_COSMETIC("Navi.EnemyPrimary.Locked"), CVAR_COSMETIC("Navi.IdleSecondary.Locked"), CVAR_COSMETIC("Navi.NPCPrimary.Locked"),
CVAR_COSMETIC("Navi.EnemySecondary.Locked"), CVAR_COSMETIC("Navi.NPCSecondary.Locked"), CVAR_COSMETIC("Navi.PropsPrimary.Locked"),
CVAR_COSMETIC("Navi.IdlePrimary.Locked"), CVAR_COSMETIC("Navi.PropsSecondary.Locked"), CVAR_COSMETIC("Link.Hair.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) { if (excludeBiddingWarColors) {
@ -575,12 +574,14 @@ void GameInteractor::RawAction::SetPlayerInvincibility(bool active) {
/// Clears the cutscene pointer to a value safe for wrong warps. /// Clears the cutscene pointer to a value safe for wrong warps.
void GameInteractor::RawAction::ClearCutscenePointer() { void GameInteractor::RawAction::ClearCutscenePointer() {
if (!gPlayState) return; if (!gPlayState)
return;
static uint32_t null_cs[] = { 0, 0 }; static uint32_t null_cs[] = { 0, 0 };
gPlayState->csCtx.segment = &null_cs; gPlayState->csCtx.segment = &null_cs;
} }
GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams) { GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId,
int32_t enemyParams) {
if (!GameInteractor::CanSpawnActor()) { if (!GameInteractor::CanSpawnActor()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@ -608,8 +609,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
// Don't allow Arwings in certain areas because they cause issues. // Don't allow Arwings in certain areas because they cause issues.
// Locations: King dodongo room, Morpha room, Twinrova room, Ganondorf room, Fishing pond, Ganon's room // Locations: King dodongo room, Morpha room, Twinrova room, Ganondorf room, Fishing pond, Ganon's room
// TODO: Swap this to disabling the option in CC options menu instead. // TODO: Swap this to disabling the option in CC options menu instead.
if (sceneNum == SCENE_DODONGOS_CAVERN_BOSS || sceneNum == SCENE_WATER_TEMPLE_BOSS || sceneNum == SCENE_SPIRIT_TEMPLE_BOSS || if (sceneNum == SCENE_DODONGOS_CAVERN_BOSS || sceneNum == SCENE_WATER_TEMPLE_BOSS ||
sceneNum == SCENE_GANONDORF_BOSS || sceneNum == SCENE_FISHING_POND || sceneNum == SCENE_GANON_BOSS) { sceneNum == SCENE_SPIRIT_TEMPLE_BOSS || sceneNum == SCENE_GANONDORF_BOSS ||
sceneNum == SCENE_FISHING_POND || sceneNum == SCENE_GANON_BOSS) {
return GameInteractionEffectQueryResult::NotPossible; return GameInteractionEffectQueryResult::NotPossible;
} }
} }
@ -649,13 +651,15 @@ 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) == NULL) { if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) ==
NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
} }
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) != NULL) { if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) !=
NULL) {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
@ -673,7 +677,8 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
if (actorId == ACTOR_EN_NIW) { if (actorId == ACTOR_EN_NIW) {
// Spawn Cucco and make it angry // Spawn Cucco and make it angry
EnNiw* cucco = (EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x, EnNiw* cucco =
(EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x,
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, actorParams, 0); player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, actorParams, 0);
if (cucco == NULL) { if (cucco == NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@ -683,7 +688,8 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} else if (actorId == ACTOR_EN_BOM) { } else if (actorId == ACTOR_EN_BOM) {
// Spawn a bomb, make it explode instantly when params is set to 1 to emulate spawning an explosion // Spawn a bomb, make it explode instantly when params is set to 1 to emulate spawning an explosion
EnBom* bomb = (EnBom*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_BOM, player->actor.world.pos.x, EnBom* bomb =
(EnBom*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_BOM, player->actor.world.pos.x,
player->actor.world.pos.y + 30, player->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true); player->actor.world.pos.y + 30, player->actor.world.pos.z, 0, 0, 0, BOMB_BODY, true);
if (bomb == NULL) { if (bomb == NULL) {
@ -704,5 +710,4 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
} }
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }

View file

@ -136,7 +136,8 @@ typedef enum {
// #### `result` // #### `result`
// ```c // ```c
// !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) // !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) &&
// Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)
// ``` // ```
// #### `args` // #### `args`
// - None // - None
@ -163,7 +164,8 @@ typedef enum {
// #### `result` // #### `result`
// ```c // ```c
// CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) // CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) &&
// !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)
// ``` // ```
// #### `args` // #### `args`
// - None // - None
@ -302,7 +304,8 @@ typedef enum {
// #### `result` // #### `result`
// ```c // ```c
// gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD // gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum !=
// SCENE_GRAVEYARD
// ``` // ```
// #### `args` // #### `args`
// - `*EnTk` // - `*EnTk`
@ -371,7 +374,8 @@ typedef enum {
// #### `result` // #### `result`
// ```c // ```c
// play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE) // play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT ||
// !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)
// ``` // ```
// #### `args` // #### `args`
// - `*EnCow` // - `*EnCow`
@ -1322,7 +1326,8 @@ typedef enum {
// Close enough & various cutscene checks // Close enough & various cutscene checks
// ```c // ```c
// (func_80AEC5FC(this, play)) && (!Play_InCsMode(play)) && // (func_80AEC5FC(this, play)) && (!Play_InCsMode(play)) &&
// (!(player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER))) && // (!(player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE |
// PLAYER_STATE1_CLIMBING_LADDER))) &&
// (player->actor.bgCheckFlags & 1) // (player->actor.bgCheckFlags & 1)
// ``` // ```
// #### `args` // #### `args`
@ -1676,7 +1681,8 @@ typedef enum {
// #### `result` // #### `result`
// ```c // ```c
// (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT // (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) &&
// !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT
// ``` // ```
// #### `args` // #### `args`
// - None // - None

View file

@ -17,4 +17,5 @@
extern PlayState* gPlayState; extern PlayState* gPlayState;
void GameConsole_Init() {} void GameConsole_Init() {
}

View file

@ -8,12 +8,10 @@
#define MAX_CVARS 2048 #define MAX_CVARS 2048
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
typedef enum typedef enum {
{
CONSOLECOMMAND_RESULT_SUCCESS, CONSOLECOMMAND_RESULT_SUCCESS,
CONSOLECOMMAND_RESULT_INVALIDARGS, CONSOLECOMMAND_RESULT_INVALIDARGS,
CONSOLECOMMAND_RESULT_INVALIDCOMMAND, CONSOLECOMMAND_RESULT_INVALIDCOMMAND,
@ -22,8 +20,7 @@ typedef enum
typedef ConsoleCommandResult (*ConsoleCommandFunc)(char** argv, s32 argc); // Returns the number of arguments it read typedef ConsoleCommandResult (*ConsoleCommandFunc)(char** argv, s32 argc); // Returns the number of arguments it read
typedef struct ConsoleCommand typedef struct ConsoleCommand {
{
char* name; char* name;
ConsoleCommandFunc func; ConsoleCommandFunc func;
char* description; char* description;

View file

@ -302,10 +302,11 @@ void LoadStatsVersion1() {
SaveManager::Instance->LoadData("fileCreatedAt", gSaveContext.ship.stats.fileCreatedAt); SaveManager::Instance->LoadData("fileCreatedAt", gSaveContext.ship.stats.fileCreatedAt);
SaveManager::Instance->LoadData("playTimer", gSaveContext.ship.stats.playTimer); SaveManager::Instance->LoadData("playTimer", gSaveContext.ship.stats.playTimer);
SaveManager::Instance->LoadData("pauseTimer", gSaveContext.ship.stats.pauseTimer); SaveManager::Instance->LoadData("pauseTimer", gSaveContext.ship.stats.pauseTimer);
SaveManager::Instance->LoadArray("itemTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.itemTimestamp), [](size_t i) { SaveManager::Instance->LoadArray(
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.itemTimestamp[i]); "itemTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.itemTimestamp),
}); [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.itemTimestamp[i]); });
SaveManager::Instance->LoadArray("sceneTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.sceneTimestamps), [&](size_t i) { SaveManager::Instance->LoadArray(
"sceneTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.sceneTimestamps), [&](size_t i) {
SaveManager::Instance->LoadStruct("", [&]() { SaveManager::Instance->LoadStruct("", [&]() {
int scene, room, sceneTime, roomTime, isRoom; int scene, room, sceneTime, roomTime, isRoom;
SaveManager::Instance->LoadData("scene", scene); SaveManager::Instance->LoadData("scene", scene);
@ -327,12 +328,12 @@ void LoadStatsVersion1() {
SaveManager::Instance->LoadArray("counts", ARRAY_COUNT(gSaveContext.ship.stats.count), [](size_t i) { SaveManager::Instance->LoadArray("counts", ARRAY_COUNT(gSaveContext.ship.stats.count), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.count[i]); SaveManager::Instance->LoadData("", gSaveContext.ship.stats.count[i]);
}); });
SaveManager::Instance->LoadArray("scenesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered), [](size_t i) { SaveManager::Instance->LoadArray(
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.scenesDiscovered[i]); "scenesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered),
}); [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.scenesDiscovered[i]); });
SaveManager::Instance->LoadArray("entrancesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered), [](size_t i) { SaveManager::Instance->LoadArray(
SaveManager::Instance->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]); "entrancesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered),
}); [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]); });
} }
void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) { void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) {
@ -350,11 +351,13 @@ void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) {
SaveManager::Instance->SaveData("fileCreatedAt", saveContext->ship.stats.fileCreatedAt); SaveManager::Instance->SaveData("fileCreatedAt", saveContext->ship.stats.fileCreatedAt);
SaveManager::Instance->SaveData("playTimer", saveContext->ship.stats.playTimer); SaveManager::Instance->SaveData("playTimer", saveContext->ship.stats.playTimer);
SaveManager::Instance->SaveData("pauseTimer", saveContext->ship.stats.pauseTimer); SaveManager::Instance->SaveData("pauseTimer", saveContext->ship.stats.pauseTimer);
SaveManager::Instance->SaveArray("itemTimestamps", ARRAY_COUNT(saveContext->ship.stats.itemTimestamp), [&](size_t i) { SaveManager::Instance->SaveArray(
SaveManager::Instance->SaveData("", saveContext->ship.stats.itemTimestamp[i]); "itemTimestamps", ARRAY_COUNT(saveContext->ship.stats.itemTimestamp),
}); [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->ship.stats.itemTimestamp[i]); });
SaveManager::Instance->SaveArray("sceneTimestamps", ARRAY_COUNT(saveContext->ship.stats.sceneTimestamps), [&](size_t i) { SaveManager::Instance->SaveArray(
if (saveContext->ship.stats.sceneTimestamps[i].scene != 254 && saveContext->ship.stats.sceneTimestamps[i].room != 254) { "sceneTimestamps", ARRAY_COUNT(saveContext->ship.stats.sceneTimestamps), [&](size_t i) {
if (saveContext->ship.stats.sceneTimestamps[i].scene != 254 &&
saveContext->ship.stats.sceneTimestamps[i].room != 254) {
SaveManager::Instance->SaveStruct("", [&]() { SaveManager::Instance->SaveStruct("", [&]() {
SaveManager::Instance->SaveData("scene", saveContext->ship.stats.sceneTimestamps[i].scene); SaveManager::Instance->SaveData("scene", saveContext->ship.stats.sceneTimestamps[i].scene);
SaveManager::Instance->SaveData("room", saveContext->ship.stats.sceneTimestamps[i].room); SaveManager::Instance->SaveData("room", saveContext->ship.stats.sceneTimestamps[i].room);
@ -368,12 +371,12 @@ void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) {
SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(saveContext->ship.stats.count), [&](size_t i) { SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(saveContext->ship.stats.count), [&](size_t i) {
SaveManager::Instance->SaveData("", saveContext->ship.stats.count[i]); SaveManager::Instance->SaveData("", saveContext->ship.stats.count[i]);
}); });
SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(saveContext->ship.stats.scenesDiscovered), [&](size_t i) { SaveManager::Instance->SaveArray(
SaveManager::Instance->SaveData("", saveContext->ship.stats.scenesDiscovered[i]); "scenesDiscovered", ARRAY_COUNT(saveContext->ship.stats.scenesDiscovered),
}); [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->ship.stats.scenesDiscovered[i]); });
SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(saveContext->ship.stats.entrancesDiscovered), [&](size_t i) { SaveManager::Instance->SaveArray(
SaveManager::Instance->SaveData("", saveContext->ship.stats.entrancesDiscovered[i]); "entrancesDiscovered", ARRAY_COUNT(saveContext->ship.stats.entrancesDiscovered),
}); [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->ship.stats.entrancesDiscovered[i]); });
} }
void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color = COLOR_WHITE, void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color = COLOR_WHITE,
@ -448,21 +451,30 @@ void DrawGameplayStatsHeader() {
GameplayStatsRow("Build Version:", (char*)gBuildVersion); GameplayStatsRow("Build Version:", (char*)gBuildVersion);
} }
if (gSaveContext.ship.stats.rtaTiming) { if (gSaveContext.ship.stats.rtaTiming) {
GameplayStatsRow("Total Time (RTA):", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE); GameplayStatsRow("Total Time (RTA):", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME),
gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
} else { } else {
GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE); GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME),
gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
} }
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowAdditionalTimers"), 0)) { // !Only display total game time if (CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowAdditionalTimers"), 0)) { // !Only display total game time
GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.playTimer / 2), COLOR_GREY); GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.playTimer / 2),
GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.pauseTimer / 3), COLOR_GREY); COLOR_GREY);
GameplayStatsRow("Time in scene:", formatTimestampGameplayStat(gSaveContext.ship.stats.sceneTimer / 2), COLOR_LIGHT_BLUE); GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.pauseTimer / 3),
GameplayStatsRow("Time in room:", formatTimestampGameplayStat(gSaveContext.ship.stats.roomTimer / 2), COLOR_LIGHT_BLUE); COLOR_GREY);
GameplayStatsRow("Time in scene:", formatTimestampGameplayStat(gSaveContext.ship.stats.sceneTimer / 2),
COLOR_LIGHT_BLUE);
GameplayStatsRow("Time in room:", formatTimestampGameplayStat(gSaveContext.ship.stats.roomTimer / 2),
COLOR_LIGHT_BLUE);
} }
if (gPlayState != NULL && CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowDebugInfo"), 0)) { // && display debug info if (gPlayState != NULL && CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowDebugInfo"), 0)) { // && display debug info
GameplayStatsRow("play->sceneNum:", formatHexGameplayStat(gPlayState->sceneNum), COLOR_YELLOW); GameplayStatsRow("play->sceneNum:", formatHexGameplayStat(gPlayState->sceneNum), COLOR_YELLOW);
GameplayStatsRow("gSaveContext.entranceIndex:", formatHexGameplayStat(gSaveContext.entranceIndex), COLOR_YELLOW); GameplayStatsRow("gSaveContext.entranceIndex:", formatHexGameplayStat(gSaveContext.entranceIndex),
GameplayStatsRow("gSaveContext.cutsceneIndex:", formatHexOnlyGameplayStat(gSaveContext.cutsceneIndex), COLOR_YELLOW); COLOR_YELLOW);
GameplayStatsRow("play->roomCtx.curRoom.num:", formatIntGameplayStat(gPlayState->roomCtx.curRoom.num), COLOR_YELLOW); GameplayStatsRow("gSaveContext.cutsceneIndex:", formatHexOnlyGameplayStat(gSaveContext.cutsceneIndex),
COLOR_YELLOW);
GameplayStatsRow("play->roomCtx.curRoom.num:", formatIntGameplayStat(gPlayState->roomCtx.curRoom.num),
COLOR_YELLOW);
} }
ImGui::EndTable(); ImGui::EndTable();
ImGui::PopStyleVar(1); ImGui::PopStyleVar(1);
@ -484,12 +496,12 @@ void DrawGameplayStatsTimestampsTab() {
for (int i = 0; i < TIMESTAMP_MAX; i++) { for (int i = 0; i < TIMESTAMP_MAX; i++) {
// To be shown, the entry must have a non-zero time and a string for its display name // To be shown, the entry must have a non-zero time and a string for its display name
if (itemTimestampDisplay[i].time > 0 && strnlen(itemTimestampDisplay[i].name, 21) > 1) { if (itemTimestampDisplay[i].time > 0 && strnlen(itemTimestampDisplay[i].name, 21) > 1) {
GameplayStatsRow(itemTimestampDisplay[i].name, formatTimestampGameplayStat(itemTimestampDisplay[i].time), itemTimestampDisplay[i].color); GameplayStatsRow(itemTimestampDisplay[i].name, formatTimestampGameplayStat(itemTimestampDisplay[i].time),
itemTimestampDisplay[i].color);
} }
} }
ImGui::EndTable(); ImGui::EndTable();
ImGui::PopStyleVar(1); ImGui::PopStyleVar(1);
} }
void DrawGameplayStatsCountsTab() { void DrawGameplayStatsCountsTab() {
@ -520,7 +532,8 @@ void DrawGameplayStatsCountsTab() {
ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch);
GameplayStatsRow("Enemies Defeated:", formatIntGameplayStat(enemiesDefeated)); GameplayStatsRow("Enemies Defeated:", formatIntGameplayStat(enemiesDefeated));
if (enemiesDefeated > 0) { if (enemiesDefeated > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Enemy Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) { if (ImGui::TreeNodeEx("Enemy Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_ENEMIES_DEFEATED_ANUBIS; i <= COUNT_ENEMIES_DEFEATED_WOLFOS; i++) { for (int i = COUNT_ENEMIES_DEFEATED_ANUBIS; i <= COUNT_ENEMIES_DEFEATED_WOLFOS; i++) {
if (i == COUNT_ENEMIES_DEFEATED_FLOORMASTER) { if (i == COUNT_ENEMIES_DEFEATED_FLOORMASTER) {
@ -537,7 +550,8 @@ void DrawGameplayStatsCountsTab() {
GameplayStatsRow("Chests Opened:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_CHESTS_OPENED])); GameplayStatsRow("Chests Opened:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_CHESTS_OPENED]));
GameplayStatsRow("Ammo Used:", formatIntGameplayStat(ammoUsed)); GameplayStatsRow("Ammo Used:", formatIntGameplayStat(ammoUsed));
if (ammoUsed > 0) { if (ammoUsed > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Ammo Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) { if (ImGui::TreeNodeEx("Ammo Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_AMMO_USED_STICK; i <= COUNT_AMMO_USED_BEAN; i++) { for (int i = COUNT_AMMO_USED_STICK; i <= COUNT_AMMO_USED_BEAN; i++) {
GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i])); GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i]));
@ -548,8 +562,10 @@ void DrawGameplayStatsCountsTab() {
GameplayStatsRow("Sword Swings:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_SWORD_SWINGS])); GameplayStatsRow("Sword Swings:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_SWORD_SWINGS]));
GameplayStatsRow("Steps Taken:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_STEPS])); GameplayStatsRow("Steps Taken:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_STEPS]));
// If using MM Bunny Hood enhancement, show how long it's been equipped (not counting pause time) // If using MM Bunny Hood enhancement, show how long it's been equipped (not counting pause time)
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] > 0) { if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA ||
GameplayStatsRow("Bunny Hood Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] / 2)); gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] > 0) {
GameplayStatsRow("Bunny Hood Time:",
formatTimestampGameplayStat(gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] / 2));
} }
GameplayStatsRow("Rolls:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_ROLLS])); GameplayStatsRow("Rolls:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_ROLLS]));
GameplayStatsRow("Bonks:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BONKS])); GameplayStatsRow("Bonks:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BONKS]));
@ -561,7 +577,8 @@ void DrawGameplayStatsCountsTab() {
GameplayStatsRow("Bushes Cut:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BUSHES_CUT])); GameplayStatsRow("Bushes Cut:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BUSHES_CUT]));
GameplayStatsRow("Buttons Pressed:", formatIntGameplayStat(buttonPresses)); GameplayStatsRow("Buttons Pressed:", formatIntGameplayStat(buttonPresses));
if (buttonPresses > 0) { if (buttonPresses > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Buttons...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) { if (ImGui::TreeNodeEx("Buttons...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_BUTTON_PRESSES_A; i <= COUNT_BUTTON_PRESSES_START; i++) { for (int i = COUNT_BUTTON_PRESSES_A; i <= COUNT_BUTTON_PRESSES_START; i++) {
GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i])); GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i]));
@ -574,16 +591,19 @@ void DrawGameplayStatsCountsTab() {
void DrawGameplayStatsBreakdownTab() { void DrawGameplayStatsBreakdownTab() {
for (int i = 0; i < gSaveContext.ship.stats.tsIdx; i++) { for (int i = 0; i < gSaveContext.ship.stats.tsIdx; i++) {
std::string sceneName = ResolveSceneID(gSaveContext.ship.stats.sceneTimestamps[i].scene, gSaveContext.ship.stats.sceneTimestamps[i].room); std::string sceneName = ResolveSceneID(gSaveContext.ship.stats.sceneTimestamps[i].scene,
gSaveContext.ship.stats.sceneTimestamps[i].room);
std::string name; std::string name;
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneTimestamps[i].scene != SCENE_GROTTOS) { if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) &&
gSaveContext.ship.stats.sceneTimestamps[i].scene != SCENE_GROTTOS) {
name = fmt::format("{:s} Room {:d}", sceneName, gSaveContext.ship.stats.sceneTimestamps[i].room); name = fmt::format("{:s} Room {:d}", sceneName, gSaveContext.ship.stats.sceneTimestamps[i].room);
} else { } else {
name = sceneName; name = sceneName;
} }
strcpy(sceneTimestampDisplay[i].name, name.c_str()); strcpy(sceneTimestampDisplay[i].name, name.c_str());
sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ? sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0)
gSaveContext.ship.stats.sceneTimestamps[i].roomTime : gSaveContext.ship.stats.sceneTimestamps[i].sceneTime; ? gSaveContext.ship.stats.sceneTimestamps[i].roomTime
: gSaveContext.ship.stats.sceneTimestamps[i].sceneTime;
sceneTimestampDisplay[i].color = COLOR_GREY; sceneTimestampDisplay[i].color = COLOR_GREY;
sceneTimestampDisplay[i].isRoom = gSaveContext.ship.stats.sceneTimestamps[i].isRoom; sceneTimestampDisplay[i].isRoom = gSaveContext.ship.stats.sceneTimestamps[i].isRoom;
} }
@ -600,7 +620,9 @@ void DrawGameplayStatsBreakdownTab() {
} }
std::string toPass; std::string toPass;
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneNum != SCENE_GROTTOS) { if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneNum != SCENE_GROTTOS) {
toPass = fmt::format("{:s} Room {:d}", ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum), gSaveContext.ship.stats.roomNum); toPass = fmt::format("{:s} Room {:d}",
ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum),
gSaveContext.ship.stats.roomNum);
} else { } else {
toPass = ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum); toPass = ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum);
} }
@ -693,7 +715,8 @@ void InitStats(bool isDebug) {
for (int scenesIdx = 0; scenesIdx < ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered); scenesIdx++) { for (int scenesIdx = 0; scenesIdx < ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered); scenesIdx++) {
gSaveContext.ship.stats.scenesDiscovered[scenesIdx] = 0; gSaveContext.ship.stats.scenesDiscovered[scenesIdx] = 0;
} }
for (int entrancesIdx = 0; entrancesIdx < ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered); entrancesIdx++) { for (int entrancesIdx = 0; entrancesIdx < ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered);
entrancesIdx++) {
gSaveContext.ship.stats.entrancesDiscovered[entrancesIdx] = 0; gSaveContext.ship.stats.entrancesDiscovered[entrancesIdx] = 0;
} }

View file

@ -19,17 +19,19 @@ extern "C" {
// Total gameplay time is tracked in tenths of seconds // Total gameplay time is tracked in tenths of seconds
// I.E. game time counts frames at 20fps/2, pause time counts frames at 30fps/3 // I.E. game time counts frames at 20fps/2, pause time counts frames at 30fps/3
// Frame counts in z_play.c and z_kaleido_scope_call.c // Frame counts in z_play.c and z_kaleido_scope_call.c
#define GAMEPLAYSTAT_TOTAL_TIME (gSaveContext.ship.stats.rtaTiming ?\ #define GAMEPLAYSTAT_TOTAL_TIME \
(!gSaveContext.ship.stats.gameComplete ?\ (gSaveContext.ship.stats.rtaTiming \
(!gSaveContext.ship.stats.fileCreatedAt ? 0 : ((GetUnixTimestamp() - gSaveContext.ship.stats.fileCreatedAt) / 100)) :\ ? (!gSaveContext.ship.stats.gameComplete \
(gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \ ? (!gSaveContext.ship.stats.fileCreatedAt \
? 0 \
: ((GetUnixTimestamp() - gSaveContext.ship.stats.fileCreatedAt) / 100)) \
: (gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \
? gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \ ? gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \
: gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED])) \ : gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED])) \
:\ : (gSaveContext.ship.stats.playTimer / 2 + gSaveContext.ship.stats.pauseTimer / 3))
(gSaveContext.ship.stats.playTimer / 2 + gSaveContext.ship.stats.pauseTimer / 3)) #define CURRENT_MODE_TIMER \
#define CURRENT_MODE_TIMER (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ?\ (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ? gSaveContext.ship.stats.roomTimer \
gSaveContext.ship.stats.roomTimer :\ : gSaveContext.ship.stats.sceneTimer)
gSaveContext.ship.stats.sceneTimer)
void InitStatTracker(); void InitStatTracker();

View file

@ -30,10 +30,17 @@ typedef enum GetItemCategory {
} GetItemCategory; } GetItemCategory;
#define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, getItemId) \ #define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, getItemId) \
{ itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, modIndex, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL } { \
itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, \
modIndex, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL \
}
#define GET_ITEM_CUSTOM_TABLE(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, tableId, getItemId) \ #define GET_ITEM_CUSTOM_TABLE(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, tableId, \
{ itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, tableId, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL } getItemId) \
{ \
itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, \
tableId, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, itemId, modIndex, NULL \
}
#define GET_ITEM_NONE \ #define GET_ITEM_NONE \
{ ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, ITEM_NONE, 0, NULL } { ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, ITEM_NONE, 0, NULL }
@ -53,10 +60,13 @@ typedef struct GetItemEntry {
/* 0x07 */ uint16_t tableId; // GetItemEntry table this entry is in (usually the same as modIndex, but not always) /* 0x07 */ uint16_t tableId; // GetItemEntry table this entry is in (usually the same as modIndex, but not always)
/* 0x08 */ int16_t getItemId; /* 0x08 */ int16_t getItemId;
/* 0x0A */ uint16_t gid; // Stores the GID value unmodified for future reference. /* 0x0A */ uint16_t gid; // Stores the GID value unmodified for future reference.
/* 0x0C */ uint16_t collectable; // determines whether the item can be collected on the overworld. Will be true in most cases. /* 0x0C */ uint16_t
collectable; // determines whether the item can be collected on the overworld. Will be true in most cases.
/* 0x0E */ GetItemFrom getItemFrom; /* 0x0E */ GetItemFrom getItemFrom;
/* 0x0F */ GetItemCategory getItemCategory; // Primarily made and used for chest size/texture matches contents /* 0x0F */ GetItemCategory getItemCategory; // Primarily made and used for chest size/texture matches contents
/* 0x10 */ uint16_t drawItemId; // Will be a copy of itemId unless the item is an ice trap. Needed for particles to function on ice traps. /* 0x10 */ uint16_t drawItemId; // Will be a copy of itemId unless the item is an ice trap. Needed for particles to
/* 0x11 */ uint16_t drawModIndex; // Will be a copy of modIndex unless the item is an ice trap. Needed for particles to function on ice traps. // function on ice traps.
/* 0x11 */ uint16_t drawModIndex; // Will be a copy of modIndex unless the item is an ice trap. Needed for particles
// to function on ice traps.
CustomDrawFunc drawFunc; CustomDrawFunc drawFunc;
} GetItemEntry; // size = 0x11 } GetItemEntry; // size = 0x11

View file

@ -30,16 +30,16 @@ namespace Rando {
void KaleidoEntryIcon::LoadIconTex(std::vector<Gfx>* mEntryDl) { void KaleidoEntryIcon::LoadIconTex(std::vector<Gfx>* mEntryDl) {
if (mIconFormat == G_IM_FMT_IA) { if (mIconFormat == G_IM_FMT_IA) {
if (mIconSize == G_IM_SIZ_8b) { if (mIconSize == G_IM_SIZ_8b) {
Gfx iconTexture[] = { gsDPLoadTextureBlock(mIconResourceName, G_IM_FMT_IA, G_IM_SIZ_8b, mIconWidth, mIconHeight, 0, Gfx iconTexture[] = { gsDPLoadTextureBlock(
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, mIconResourceName, G_IM_FMT_IA, G_IM_SIZ_8b, mIconWidth, mIconHeight, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOLOD, G_TX_NOLOD) }; G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture)); mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture));
} }
} else if (mIconFormat == G_IM_FMT_RGBA) { } else if (mIconFormat == G_IM_FMT_RGBA) {
if (mIconSize == G_IM_SIZ_32b) { if (mIconSize == G_IM_SIZ_32b) {
Gfx iconTexture[] = { gsDPLoadTextureBlock(mIconResourceName, G_IM_FMT_RGBA, G_IM_SIZ_32b, mIconWidth, mIconHeight, 0, Gfx iconTexture[] = { gsDPLoadTextureBlock(
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, mIconResourceName, G_IM_FMT_RGBA, G_IM_SIZ_32b, mIconWidth, mIconHeight, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOLOD, G_TX_NOLOD) }; G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture)); mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture));
} }
} }
@ -71,7 +71,8 @@ namespace Rando {
Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY); Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY);
mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW)); mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW));
// icon // icon
if (!mAchieved) { if (!mAchieved) {
@ -99,9 +100,9 @@ namespace Rando {
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i])); auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16)); auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b( Gfx charTexture[] = { gsDPLoadTextureBlock_4b(texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) }; G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture)); mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0)); mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
} }
@ -111,15 +112,14 @@ namespace Rando {
Kaleido::Kaleido() { Kaleido::Kaleido() {
const auto ctx = Rando::Context::GetInstance(); const auto ctx = Rando::Context::GetInstance();
int yOffset = 2; int yOffset = 2;
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(gRupeeCounterIconTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
Color_RGBA8{ 0xC8, 0xFF, 0x64, 255 }, FlagType::FLAG_RANDOMIZER_INF, gRupeeCounterIconTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, Color_RGBA8{ 0xC8, 0xFF, 0x64, 255 },
static_cast<int>(RAND_INF_GREG_FOUND), 0, yOffset, "Greg")); FlagType::FLAG_RANDOMIZER_INF, static_cast<int>(RAND_INF_GREG_FOUND), 0, yOffset, "Greg"));
yOffset += 18; yOffset += 18;
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) { if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
mEntries.push_back( mEntries.push_back(std::make_shared<KaleidoEntryIconCountRequired>(
std::make_shared<KaleidoEntryIconCountRequired>( gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 }, 0, yOffset,
gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255,255,255,255 }, 0, reinterpret_cast<int*>(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected),
yOffset, reinterpret_cast<int*>(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected),
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1, ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1,
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1)); ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1));
yOffset += 18; yOffset += 18;
@ -130,32 +130,20 @@ namespace Rando {
} }
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).IsNot(RO_BOSS_SOULS_OFF)) { if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).IsNot(RO_BOSS_SOULS_OFF)) {
static const char* bossSoulNames[] = { static const char* bossSoulNames[] = {
"Gohma's Soul", "Gohma's Soul", "King Dodongo's Soul", "Barinade's Soul", "Phantom Ganon's Soul",
"King Dodongo's Soul", "Volvagia's Soul", "Morpha's Soul", "Bongo Bongo's Soul", "Twinrova's Soul",
"Barinade's Soul",
"Phantom Ganon's Soul",
"Volvagia's Soul",
"Morpha's Soul",
"Bongo Bongo's Soul",
"Twinrova's Soul",
}; };
for (int i = RAND_INF_GOHMA_SOUL; i < RAND_INF_GANON_SOUL; i++) { for (int i = RAND_INF_GOHMA_SOUL; i < RAND_INF_GANON_SOUL; i++) {
mEntries.push_back( mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
std::make_shared<KaleidoEntryIconFlag>(
gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 }, gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
FlagType::FLAG_RANDOMIZER_INF, i, 0, yOffset, bossSoulNames[i - RAND_INF_GOHMA_SOUL] FlagType::FLAG_RANDOMIZER_INF, i, 0, yOffset, bossSoulNames[i - RAND_INF_GOHMA_SOUL]));
)
);
yOffset += 18; yOffset += 18;
} }
} }
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON)) { if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON)) {
mEntries.push_back( mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
std::make_shared<KaleidoEntryIconFlag>(
gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 }, gBossSoulTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
FlagType::FLAG_RANDOMIZER_INF, RAND_INF_GANON_SOUL, 0, yOffset, "Ganon's Soul" FlagType::FLAG_RANDOMIZER_INF, RAND_INF_GANON_SOUL, 0, yOffset, "Ganon's Soul"));
)
);
yOffset += 18; yOffset += 18;
} }
} }
@ -211,12 +199,14 @@ namespace Rando {
} 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) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
pauseCtx->cursorSpecialPos = 0; pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} }
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) { } else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) {
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
pauseCtx->cursorSpecialPos = 0; pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} }
} }
} else if (pauseCtx->cursorSpecialPos != 0 && pauseCtx->state == 7) { } else if (pauseCtx->cursorSpecialPos != 0 && pauseCtx->state == 7) {
@ -229,7 +219,8 @@ namespace Rando {
if (shouldScroll) { if (shouldScroll) {
entry->SetYOffset(yOffset); entry->SetYOffset(yOffset);
yOffset += 18; yOffset += 18;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} }
Matrix_Push(); Matrix_Push();
entry->Draw(play, &mEntryDl); entry->Draw(play, &mEntryDl);
@ -261,9 +252,9 @@ namespace Rando {
KaleidoEntryIconFlag::KaleidoEntryIconFlag(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth, KaleidoEntryIconFlag::KaleidoEntryIconFlag(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, FlagType flagType, int flag, int iconHeight, Color_RGBA8 iconColor, FlagType flagType, int flag,
int16_t x, int16_t y, std::string name) : int16_t x, int16_t y, std::string name)
mFlagType(flagType), mFlag(flag), : mFlagType(flagType), mFlag(flag), KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight,
KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y, std::move(name)) { iconColor, x, y, std::move(name)) {
BuildVertices(); BuildVertices();
} }
@ -271,9 +262,10 @@ namespace Rando {
mAchieved = GameInteractor::RawAction::CheckFlag(mFlagType, static_cast<int16_t>(mFlag)); mAchieved = GameInteractor::RawAction::CheckFlag(mFlagType, static_cast<int16_t>(mFlag));
} }
KaleidoEntryIconCountRequired::KaleidoEntryIconCountRequired(const char *iconResourceName, int iconFormat, KaleidoEntryIconCountRequired::KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize,
int iconSize, int iconWidth, int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch, int iconWidth, int iconHeight, Color_RGBA8 iconColor,
int required, int total) : mWatch(watch), mRequired(required), mTotal(total), int16_t x, int16_t y, int* watch, int required, int total)
: mWatch(watch), mRequired(required), mTotal(total),
KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y) { KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y) {
mCount = *mWatch; mCount = *mWatch;
BuildText(); BuildText();
@ -318,9 +310,9 @@ namespace Rando {
KaleidoEntryIcon::KaleidoEntryIcon(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth, KaleidoEntryIcon::KaleidoEntryIcon(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text) int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text)
: mIconResourceName(iconResourceName), mIconFormat(iconFormat), mIconSize(iconSize), : mIconResourceName(iconResourceName), mIconFormat(iconFormat), mIconSize(iconSize), mIconWidth(iconWidth),
mIconWidth(iconWidth), mIconHeight(iconHeight), mIconColor(iconColor), mIconHeight(iconHeight), mIconColor(iconColor), KaleidoEntry(x, y, std::move(text)) {
KaleidoEntry(x, y, std::move(text)) {} }
void KaleidoEntryIcon::RebuildVertices() { void KaleidoEntryIcon::RebuildVertices() {
free(vtx); free(vtx);
@ -335,11 +327,10 @@ namespace Rando {
RebuildVertices(); RebuildVertices();
mAchieved = mCount >= mRequired; mAchieved = mCount >= mRequired;
} }
} }
KaleidoEntryOcarinaButtons::KaleidoEntryOcarinaButtons(int16_t x, int16_t y) : KaleidoEntryOcarinaButtons::KaleidoEntryOcarinaButtons(int16_t x, int16_t y)
KaleidoEntryIcon(gItemIconOcarinaOfTimeTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, : KaleidoEntryIcon(gItemIconOcarinaOfTimeTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32,
Color_RGBA8{ 255, 255, 255, 255 }, x, y, "\x9F\xA5\xA6\xA7\xA8") { Color_RGBA8{ 255, 255, 255, 255 }, x, y, "\x9F\xA5\xA6\xA7\xA8") {
CalculateColors(); CalculateColors();
BuildVertices(); BuildVertices();
@ -411,7 +402,8 @@ namespace Rando {
Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY); Matrix_Translate(mX, mY, 0.0f, MTXMODE_APPLY);
// Matrix_Scale(0.75f, 0.75f, 0.75f, MTXMODE_APPLY); // Matrix_Scale(0.75f, 0.75f, 0.75f, MTXMODE_APPLY);
mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW)); mEntryDl->push_back(gsSPMatrix(Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW));
// icon // icon
if (!mAchieved) { if (!mAchieved) {
@ -426,7 +418,8 @@ namespace Rando {
// text // text
for (size_t i = 0, vtxGroup = 0; i < numChar; i++) { for (size_t i = 0, vtxGroup = 0; i < numChar; i++) {
mEntryDl->push_back(gsDPSetPrimColor(0, 0, mButtonColors[i].r, mButtonColors[i].g, mButtonColors[i].b, mButtonColors[i].a)); mEntryDl->push_back(
gsDPSetPrimColor(0, 0, mButtonColors[i].r, mButtonColors[i].g, mButtonColors[i].b, mButtonColors[i].a));
// A maximum of 64 Vtx can be loaded at once by gSPVertex, or basically 16 characters // A maximum of 64 Vtx can be loaded at once by gSPVertex, or basically 16 characters
// handle loading groups of 16 chars at a time until there are no more left to load. // handle loading groups of 16 chars at a time until there are no more left to load.
@ -440,16 +433,17 @@ namespace Rando {
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i])); auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16)); auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b( Gfx charTexture[] = { gsDPLoadTextureBlock_4b(texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) }; G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture)); mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0)); mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
} }
mEntryDl->push_back(gsSPPopMatrix(G_MTX_MODELVIEW)); mEntryDl->push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
} }
} // Rando } // namespace Rando
void RandoKaleido_RegisterHooks() { void RandoKaleido_RegisterHooks() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoscopeUpdate>(RandoKaleido_UpdateMiscCollectibles); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoscopeUpdate>(
RandoKaleido_UpdateMiscCollectibles);
} }

View file

@ -2,7 +2,6 @@
#define KALEIDO_H #define KALEIDO_H
#include <z64.h> #include <z64.h>
#ifdef __cplusplus #ifdef __cplusplus
#include <vector> #include <vector>
#include <string> #include <string>
@ -31,6 +30,7 @@ public:
virtual void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) = 0; virtual void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) = 0;
virtual void Update(PlayState* play) = 0; virtual void Update(PlayState* play) = 0;
void SetYOffset(int yOffset); void SetYOffset(int yOffset);
protected: protected:
int16_t mX; int16_t mX;
int16_t mY; int16_t mY;
@ -39,7 +39,6 @@ protected:
Vtx* vtx; Vtx* vtx;
std::string mText; std::string mText;
bool mAchieved = false; bool mAchieved = false;
}; };
/** /**
@ -63,6 +62,7 @@ public:
Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text = ""); Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text = "");
void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override; void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override;
void RebuildVertices(); void RebuildVertices();
protected: protected:
const char* mIconResourceName; const char* mIconResourceName;
int mIconFormat; int mIconFormat;
@ -98,6 +98,7 @@ public :
Color_RGBA8 iconColor, FlagType flagType, int flag, int16_t x, int16_t y, Color_RGBA8 iconColor, FlagType flagType, int flag, int16_t x, int16_t y,
std::string name = ""); std::string name = "");
void Update(PlayState* play) override; void Update(PlayState* play) override;
private: private:
FlagType mFlagType; FlagType mFlagType;
int mFlag; int mFlag;
@ -126,9 +127,11 @@ public:
* @param required The amount of this collectible required to beat the seed. Set to 0 to not render. * @param required The amount of this collectible required to beat the seed. Set to 0 to not render.
* @param total The amount of this collectible available in the seed. Set to 0 to not render. * @param total The amount of this collectible available in the seed. Set to 0 to not render.
*/ */
KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth, int iconHeight, KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch, int required = 0, int total = 0); int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch,
int required = 0, int total = 0);
void Update(PlayState* play) override; void Update(PlayState* play) override;
private: private:
int* mWatch; int* mWatch;
int mRequired; int mRequired;
@ -143,6 +146,7 @@ public:
KaleidoEntryOcarinaButtons(int16_t x, int16_t y); KaleidoEntryOcarinaButtons(int16_t x, int16_t y);
void Update(PlayState* play) override; void Update(PlayState* play) override;
void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override; void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override;
private: private:
void CalculateColors(); void CalculateColors();
@ -155,13 +159,14 @@ public:
Kaleido(); Kaleido();
void Draw(PlayState* play); void Draw(PlayState* play);
void Update(PlayState* play); void Update(PlayState* play);
private: private:
std::vector<std::shared_ptr<KaleidoEntry>> mEntries; std::vector<std::shared_ptr<KaleidoEntry>> mEntries;
std::vector<Gfx> mEntryDl; std::vector<Gfx> mEntryDl;
int mTopIndex = 0; int mTopIndex = 0;
int mNumVisible = 7; int mNumVisible = 7;
}; };
} // Rando } // namespace Rando
extern "C" { extern "C" {
#endif #endif
@ -172,5 +177,4 @@ void RandoKaleido_UpdateMiscCollectibles(int16_t inDungeonScene);
#endif #endif
void RandoKaleido_RegisterHooks(); void RandoKaleido_RegisterHooks();
#endif // KALEIDO_H #endif // KALEIDO_H

View file

@ -66,7 +66,8 @@ static const ALIGN_ASSET(2) char tokinoma_room_0DL_007FD0[] = dtokinoma_room_0DL
/// Switches Link's age and respawns him at the last entrance he entered. /// Switches Link's age and respawns him at the last entrance he entered.
void SwitchAge() { void SwitchAge() {
if (gPlayState == NULL) return; if (gPlayState == NULL)
return;
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
@ -114,14 +115,16 @@ void RegisterOcarinaTimeTravel() {
} }
Actor* player = &GET_PLAYER(gPlayState)->actor; Actor* player = &GET_PLAYER(gPlayState)->actor;
Actor* nearbyTimeBlockEmpty = Actor_FindNearby(gPlayState, player, ACTOR_OBJ_WARP2BLOCK, ACTORCAT_ITEMACTION, 300.0f); Actor* nearbyTimeBlockEmpty =
Actor_FindNearby(gPlayState, player, ACTOR_OBJ_WARP2BLOCK, ACTORCAT_ITEMACTION, 300.0f);
Actor* nearbyTimeBlock = Actor_FindNearby(gPlayState, player, ACTOR_OBJ_TIMEBLOCK, ACTORCAT_ITEMACTION, 300.0f); Actor* nearbyTimeBlock = Actor_FindNearby(gPlayState, player, ACTOR_OBJ_TIMEBLOCK, ACTORCAT_ITEMACTION, 300.0f);
Actor* nearbyOcarinaSpot = Actor_FindNearby(gPlayState, player, ACTOR_EN_OKARINA_TAG, ACTORCAT_PROP, 120.0f); Actor* nearbyOcarinaSpot = Actor_FindNearby(gPlayState, player, ACTOR_EN_OKARINA_TAG, ACTORCAT_PROP, 120.0f);
Actor* nearbyDoorOfTime = Actor_FindNearby(gPlayState, player, ACTOR_DOOR_TOKI, ACTORCAT_BG, 500.0f); Actor* nearbyDoorOfTime = Actor_FindNearby(gPlayState, player, ACTOR_DOOR_TOKI, ACTORCAT_BG, 500.0f);
Actor* nearbyFrogs = Actor_FindNearby(gPlayState, player, ACTOR_EN_FR, ACTORCAT_NPC, 300.0f); Actor* nearbyFrogs = Actor_FindNearby(gPlayState, player, ACTOR_EN_FR, ACTORCAT_NPC, 300.0f);
Actor* nearbyGossipStone = Actor_FindNearby(gPlayState, player, ACTOR_EN_GS, ACTORCAT_NPC, 300.0f); Actor* nearbyGossipStone = Actor_FindNearby(gPlayState, player, ACTOR_EN_GS, ACTORCAT_NPC, 300.0f);
bool justPlayedSoT = gPlayState->msgCtx.lastPlayedSong == OCARINA_SONG_TIME; bool justPlayedSoT = gPlayState->msgCtx.lastPlayedSong == OCARINA_SONG_TIME;
bool notNearAnySource = !nearbyTimeBlockEmpty && !nearbyTimeBlock && !nearbyOcarinaSpot && !nearbyDoorOfTime && !nearbyFrogs && !nearbyGossipStone; bool notNearAnySource = !nearbyTimeBlockEmpty && !nearbyTimeBlock && !nearbyOcarinaSpot && !nearbyDoorOfTime &&
!nearbyFrogs && !nearbyGossipStone;
bool hasOcarinaOfTime = (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME); bool hasOcarinaOfTime = (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME);
bool doesntNeedOcarinaOfTime = CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2; bool doesntNeedOcarinaOfTime = CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2;
bool hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER); bool hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER);
@ -191,13 +194,14 @@ void RegisterShadowTag() {
static bool hasAffectedHealth = false; static bool hasAffectedHealth = false;
void UpdatePermanentHeartLossState() { void UpdatePermanentHeartLossState() {
if (!GameInteractor::IsSaveLoaded()) return; if (!GameInteractor::IsSaveLoaded())
return;
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) { if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) {
uint8_t heartContainers = gSaveContext.ship.stats.heartContainers; // each worth 16 health uint8_t heartContainers = gSaveContext.ship.stats.heartContainers; // each worth 16 health
uint8_t heartPieces = gSaveContext.ship.stats.heartPieces; // each worth 4 health, but only in groups of 4 uint8_t heartPieces = gSaveContext.ship.stats.heartPieces; // each worth 4 health, but only in groups of 4
uint8_t startingHealth = 16 * (IS_RANDO ? (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_HEARTS) + 1) : 3); uint8_t startingHealth =
16 * (IS_RANDO ? (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_HEARTS) + 1) : 3);
uint8_t newCapacity = startingHealth + (heartContainers * 16) + ((heartPieces - (heartPieces % 4)) * 4); uint8_t newCapacity = startingHealth + (heartContainers * 16) + ((heartPieces - (heartPieces % 4)) * 4);
gSaveContext.healthCapacity = MAX(newCapacity, gSaveContext.healthCapacity); gSaveContext.healthCapacity = MAX(newCapacity, gSaveContext.healthCapacity);
@ -213,7 +217,8 @@ void RegisterPermanentHeartLoss() {
}); });
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) || !GameInteractor::IsSaveLoaded()) return; if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) || !GameInteractor::IsSaveLoaded())
return;
if (gSaveContext.healthCapacity > 16 && gSaveContext.healthCapacity - gSaveContext.health >= 16) { if (gSaveContext.healthCapacity > 16 && gSaveContext.healthCapacity - gSaveContext.health >= 16) {
gSaveContext.healthCapacity -= 16; gSaveContext.healthCapacity -= 16;
@ -225,12 +230,16 @@ void RegisterPermanentHeartLoss() {
void RegisterDeleteFileOnDeath() { void RegisterDeleteFileOnDeath() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!CVarGetInteger(CVAR_ENHANCEMENT("DeleteFileOnDeath"), 0) || !GameInteractor::IsSaveLoaded() || gPlayState == NULL) return; if (!CVarGetInteger(CVAR_ENHANCEMENT("DeleteFileOnDeath"), 0) || !GameInteractor::IsSaveLoaded() ||
gPlayState == NULL)
return;
if (gPlayState->gameOverCtx.state == GAMEOVER_DEATH_MENU && gPlayState->pauseCtx.state == 9) { if (gPlayState->gameOverCtx.state == GAMEOVER_DEATH_MENU && gPlayState->pauseCtx.state == 9) {
SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum); SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum);
hasAffectedHealth = false; hasAffectedHealth = false;
std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset"); std::reinterpret_pointer_cast<Ship::ConsoleWindow>(
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))
->Dispatch("reset");
} }
}); });
} }
@ -258,7 +267,10 @@ void RegisterDaytimeGoldSkultullas() {
// ZF // ZF
{ SCENE_ZORAS_FOUNTAIN, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } }, { SCENE_ZORAS_FOUNTAIN, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } },
// GF // GF
{ SCENE_GERUDOS_FORTRESS, 0, false, { { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } }, { SCENE_GERUDOS_FORTRESS,
0,
false,
{ { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } },
{ SCENE_GERUDOS_FORTRESS, 1, false, { { ACTOR_EN_SW, { 3377, 1734, -4935 }, { 16384, 0, 0 }, -19199 } } }, { SCENE_GERUDOS_FORTRESS, 1, false, { { ACTOR_EN_SW, { 3377, 1734, -4935 }, { 16384, 0, 0 }, -19199 } } },
// Kak // Kak
{ SCENE_KAKARIKO_VILLAGE, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } }, { SCENE_KAKARIKO_VILLAGE, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } },
@ -293,7 +305,8 @@ void RegisterDaytimeGoldSkultullas() {
bool IsHyperBossesActive() { bool IsHyperBossesActive() {
return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) || return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) ||
(IS_BOSS_RUSH && gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES); (IS_BOSS_RUSH &&
gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
} }
void UpdateHyperBossesState() { void UpdateHyperBossesState() {
@ -304,21 +317,22 @@ void UpdateHyperBossesState() {
} }
if (IsHyperBossesActive()) { if (IsHyperBossesActive()) {
actorUpdateHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) { actorUpdateHookId =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make bosses move and act twice as fast. // Run the update function a second time to make bosses move and act twice as fast.
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor); Actor* actor = static_cast<Actor*>(refActor);
uint8_t isBossActor = uint8_t isBossActor = actor->id == ACTOR_BOSS_GOMA || // Gohma
actor->id == ACTOR_BOSS_GOMA || // Gohma
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath
actor->id == ACTOR_BOSS_VA || // Barinade actor->id == ACTOR_BOSS_VA || // Barinade
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder
actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse
actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying) actor->id == ACTOR_BOSS_FD ||
actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying)
actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks
actor->id == ACTOR_BOSS_MO || // Morpha actor->id == ACTOR_BOSS_MO || // Morpha
actor->id == ACTOR_BOSS_SST || // Bongo Bongo actor->id == ACTOR_BOSS_SST || // Bongo Bongo
@ -348,9 +362,8 @@ void UpdateHyperBossesState() {
void RegisterHyperBosses() { void RegisterHyperBosses() {
UpdateHyperBossesState(); UpdateHyperBossesState();
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int16_t fileNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>(
UpdateHyperBossesState(); [](int16_t fileNum) { UpdateHyperBossesState(); });
});
} }
void UpdateHyperEnemiesState() { void UpdateHyperEnemiesState() {
@ -361,7 +374,8 @@ void UpdateHyperEnemiesState() {
} }
if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0)) { if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0)) {
actorUpdateHookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) { actorUpdateHookId =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make enemies and minibosses move and act twice as fast. // Run the update function a second time to make enemies and minibosses move and act twice as fast.
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
@ -428,7 +442,8 @@ void UpdateDirtPathFixState(int32_t sceneNum) {
case SCENE_HYRULE_FIELD: case SCENE_HYRULE_FIELD:
case SCENE_KOKIRI_FOREST: case SCENE_KOKIRI_FOREST:
case SCENE_HYRULE_CASTLE: case SCENE_HYRULE_CASTLE:
CVarSetInteger(CVAR_Z_FIGHTING_MODE, CVarGetInteger(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_DISABLED)); CVarSetInteger(CVAR_Z_FIGHTING_MODE,
CVarGetInteger(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_DISABLED));
return; return;
default: default:
CVarClear(CVAR_Z_FIGHTING_MODE); CVarClear(CVAR_Z_FIGHTING_MODE);
@ -436,9 +451,8 @@ void UpdateDirtPathFixState(int32_t sceneNum) {
} }
void RegisterMenuPathFix() { void RegisterMenuPathFix() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>([](int32_t sceneNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(
UpdateDirtPathFixState(sceneNum); [](int32_t sceneNum) { UpdateDirtPathFixState(sceneNum); });
});
} }
void UpdateMirrorModeState(int32_t sceneNum) { void UpdateMirrorModeState(int32_t sceneNum) {
@ -446,27 +460,28 @@ void UpdateMirrorModeState(int32_t sceneNum) {
bool nextMirroredWorld = false; bool nextMirroredWorld = false;
int16_t mirroredMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorldMode"), MIRRORED_WORLD_OFF); int16_t mirroredMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorldMode"), MIRRORED_WORLD_OFF);
int16_t inDungeon = (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_INSIDE_GANONS_CASTLE_COLLAPSE && sceneNum != SCENE_THIEVES_HIDEOUT) || int16_t inDungeon = (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_INSIDE_GANONS_CASTLE_COLLAPSE &&
sceneNum != SCENE_THIEVES_HIDEOUT) ||
(sceneNum >= SCENE_DEKU_TREE_BOSS && sceneNum <= SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) || (sceneNum >= SCENE_DEKU_TREE_BOSS && sceneNum <= SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) ||
(sceneNum == SCENE_GANON_BOSS); (sceneNum == SCENE_GANON_BOSS);
if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) { if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) {
uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() uint32_t seed =
: gSaveContext.ship.stats.fileCreatedAt); sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(seed); Random_Init(seed);
} }
bool randomMirror = Random(0, 2) == 1; bool randomMirror = Random(0, 2) == 1;
if ( if (mirroredMode == MIRRORED_WORLD_ALWAYS ||
mirroredMode == MIRRORED_WORLD_ALWAYS ||
((mirroredMode == MIRRORED_WORLD_RANDOM || mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED) && randomMirror) || ((mirroredMode == MIRRORED_WORLD_RANDOM || mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED) && randomMirror) ||
// Dungeon modes // Dungeon modes
(inDungeon && (mirroredMode == MIRRORED_WORLD_DUNGEONS_ALL || (inDungeon &&
(mirroredMode == MIRRORED_WORLD_DUNGEONS_ALL ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_VANILLA && !ResourceMgr_IsSceneMasterQuest(sceneNum)) || (mirroredMode == MIRRORED_WORLD_DUNGEONS_VANILLA && !ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_MQ && ResourceMgr_IsSceneMasterQuest(sceneNum)) || (mirroredMode == MIRRORED_WORLD_DUNGEONS_MQ && ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
((mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) && randomMirror))) ((mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) &&
) { randomMirror)))) {
nextMirroredWorld = true; nextMirroredWorld = true;
CVarSetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 1); CVarSetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 1);
} else { } else {
@ -481,25 +496,33 @@ void UpdateMirrorModeState(int32_t sceneNum) {
} }
void RegisterMirrorModeHandler() { void RegisterMirrorModeHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(
UpdateMirrorModeState(sceneNum); [](int32_t sceneNum) { UpdateMirrorModeState(sceneNum); });
});
} }
void UpdatePatchHand() { void UpdatePatchHand() {
if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_CHILD) { if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_CHILD) {
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1", 92, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1", 92,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer2", 93, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer2", 93, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84,
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2", 85, gsSPEndDisplayList()); gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1", 51, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2", 85,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1", 51,
gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow2", 52, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow2", 52, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1", 104, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1", 104,
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2", 105, gsSPEndDisplayList()); gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1", 79, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2", 105,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1", 79,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2", 80, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2", 80, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1", 76, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1", 76,
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2", 77, gsSPEndDisplayList()); gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2", 77,
gsSPEndDisplayList());
} else { } else {
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1"); ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1");
@ -516,10 +539,14 @@ void UpdatePatchHand() {
ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2"); ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2");
} }
if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_ADULT) { if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_ADULT) {
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13,
ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL)); gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13,
ResourceMgr_PatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield", 49, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL)); gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50,
gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield", 49,
gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
} else { } else {
ResourceMgr_UnpatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword"); ResourceMgr_UnpatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword");
ResourceMgr_UnpatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot"); ResourceMgr_UnpatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot");
@ -527,7 +554,8 @@ void UpdatePatchHand() {
ResourceMgr_UnpatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield"); ResourceMgr_UnpatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield");
} }
if (CVarGetInteger("gEnhancements.FixHammerHand", 0) && LINK_IS_ADULT) { if (CVarGetInteger("gEnhancements.FixHammerHand", 0) && LINK_IS_ADULT) {
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1", 92, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL)); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1", 92,
gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand2", 93, gsSPEndDisplayList()); ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand2", 93, gsSPEndDisplayList());
} else { } else {
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1"); ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1");
@ -536,9 +564,8 @@ void UpdatePatchHand() {
} }
void RegisterPatchHandHandler() { void RegisterPatchHandHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(
UpdatePatchHand(); [](int32_t sceneNum) { UpdatePatchHand(); });
});
} }
void RegisterResetNaviTimer() { void RegisterResetNaviTimer() {
@ -655,16 +682,14 @@ void RegisterEnemyDefeatCounts() {
} }
break; break;
case ACTOR_EN_REEBA: case ACTOR_EN_REEBA: {
{
EnReeba* reeba = (EnReeba*)actor; EnReeba* reeba = (EnReeba*)actor;
if (reeba->isBig) { if (reeba->isBig) {
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++; gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++;
} else { } else {
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++; gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
} }
} } break;
break;
case ACTOR_EN_MB: case ACTOR_EN_MB:
if (actor->params == 0) { if (actor->params == 0) {
@ -798,9 +823,8 @@ void UpdateHurtContainerModeState(bool newState) {
} }
void RegisterHurtContainerModeHandler() { void RegisterHurtContainerModeHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>(
UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0)); [](int32_t fileNum) { UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0)); });
});
} }
void RegisterRandomizedEnemySizes() { void RegisterRandomizedEnemySizes() {
@ -820,7 +844,8 @@ void RegisterRandomizedEnemySizes() {
actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH; actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH;
// Only apply to enemies and bosses. // Only apply to enemies and bosses.
if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemySizes"), 0) || (actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) { if (!CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemySizes"), 0) ||
(actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) {
return; return;
} }
@ -860,7 +885,8 @@ void RegisterOpenAllHours() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
Actor* actor = static_cast<Actor*>(refActor); Actor* actor = static_cast<Actor*>(refActor);
if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR) && (!IS_RANDO || !OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOCK_OVERWORLD_DOORS))) { if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR) &&
(!IS_RANDO || !OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOCK_OVERWORLD_DOORS))) {
switch (actor->params) { switch (actor->params) {
case 4753: // Night Market Bazaar case 4753: // Night Market Bazaar
case 1678: // Night Potion Shop case 1678: // Night Potion Shop
@ -892,47 +918,65 @@ void PatchToTMedallions() {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_StartGrayscale", 7, gsSPGrayscale(true)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_StartGrayscale", 7, gsSPGrayscale(true));
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16, gsDPSetGrayscaleColor(0, 161, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16,
gsDPSetGrayscaleColor(0, 161, 255, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45, gsDPSetGrayscaleColor(255, 135, 0, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45,
gsDPSetGrayscaleColor(255, 135, 0, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69, gsDPSetGrayscaleColor(255, 255, 0, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69,
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16, gsDPSetGrayscaleColor(255, 255, 0, 255)); gsDPSetGrayscaleColor(255, 255, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16,
gsDPSetGrayscaleColor(255, 255, 0, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69,
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16, gsDPSetGrayscaleColor(255, 255, 255, 255)); gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94, gsDPSetGrayscaleColor(0, 255, 0, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94,
gsDPSetGrayscaleColor(0, 255, 0, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118, gsDPSetGrayscaleColor(255, 0, 0, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118,
gsDPSetGrayscaleColor(255, 0, 0, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142, gsDPSetGrayscaleColor(212, 0, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142,
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27, gsDPSetGrayscaleColor(212, 0, 255, 255)); gsDPSetGrayscaleColor(212, 0, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27,
gsDPSetGrayscaleColor(212, 0, 255, 255));
} else { } else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142, gsDPSetGrayscaleColor(255, 255, 255, 255)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142,
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27, gsDPSetGrayscaleColor(255, 255, 255, 255)); gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27,
gsDPSetGrayscaleColor(255, 255, 255, 255));
} }
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_EndGrayscaleAndEndDlist", 160, gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL)); ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_EndGrayscaleAndEndDlist", 160,
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_EndGrayscaleAndEndDlist", 51, gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL)); gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_EndGrayscaleAndEndDlist", 51,
gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
} else { } else {
// Unpatch everything // Unpatch everything
ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_StartGrayscale"); ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_StartGrayscale");
@ -953,7 +997,8 @@ void PatchToTMedallions() {
void RegisterToTMedallions() { void RegisterToTMedallions() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry _unused) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry _unused) {
if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || !gPlayState || gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) { if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || !gPlayState ||
gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) {
return; return;
} }
PatchToTMedallions(); PatchToTMedallions();
@ -966,7 +1011,6 @@ void RegisterToTMedallions() {
}); });
} }
void RegisterFloorSwitchesHook() { void RegisterFloorSwitchesHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
Actor* actor = static_cast<Actor*>(refActor); Actor* actor = static_cast<Actor*>(refActor);
@ -991,10 +1035,10 @@ void RegisterPauseMenuHooks() {
return; return;
} }
if (!pauseWarpHooksRegistered) { if (!pauseWarpHooksRegistered) {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoUpdate>([]() {PauseWarp_HandleSelection();}); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoUpdate>(
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() { []() { PauseWarp_HandleSelection(); });
PauseWarp_Execute(); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(
}); []() { PauseWarp_Execute(); });
pauseWarpHooksRegistered = true; pauseWarpHooksRegistered = true;
} }
}); });
@ -1004,7 +1048,6 @@ void RegisterCustomSkeletons() {
static int8_t previousTunic = -1; static int8_t previousTunic = -1;
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded() || gPlayState == NULL) { if (!GameInteractor::IsSaveLoaded() || gPlayState == NULL) {
return; return;
} }

View file

@ -130,9 +130,9 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
int16_t vertexStart = 4 * (i % 16); int16_t vertexStart = 4 * (i % 16);
// Multi-instruction macro, need to insert all to the dl buffer // Multi-instruction macro, need to insert all to the dl buffer
Gfx charTexture[] = { gsDPLoadTextureBlock_4b( Gfx charTexture[] = { gsDPLoadTextureBlock_4b(texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) }; G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
nameTagDl.insert(nameTagDl.end(), std::begin(charTexture), std::end(charTexture)); nameTagDl.insert(nameTagDl.end(), std::begin(charTexture), std::end(charTexture));
nameTagDl.push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0)); nameTagDl.push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
@ -195,11 +195,14 @@ extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* te
std::string processedText = std::string(Interface_ReplaceSpecialCharacters((char*)text)); std::string processedText = std::string(Interface_ReplaceSpecialCharacters((char*)text));
// Strip out unsupported characters // Strip out unsupported characters
processedText.erase(std::remove_if(processedText.begin(), processedText.end(), [](const char& c) { processedText.erase(std::remove_if(processedText.begin(), processedText.end(),
[](const char& c) {
// 172 is max supported texture for the in-game font system, // 172 is max supported texture for the in-game font system,
// and filter anything less than a space but not the newline or nul characters // and filter anything less than a space but not the newline or nul
// characters
return (unsigned char)c > 172 || (c < ' ' && c != '\n' && c != '\0'); return (unsigned char)c > 172 || (c < ' ' && c != '\n' && c != '\0');
}), processedText.end()); }),
processedText.end());
int16_t numChar = processedText.length(); int16_t numChar = processedText.length();
int16_t numLines = 1; int16_t numLines = 1;

View file

@ -5,21 +5,13 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
static const int songMessageMap[] = { static const int songMessageMap[] = {
TEXT_WARP_MINUET_OF_FOREST, TEXT_WARP_MINUET_OF_FOREST, TEXT_WARP_BOLERO_OF_FIRE, TEXT_WARP_SERENADE_OF_WATER,
TEXT_WARP_BOLERO_OF_FIRE, TEXT_WARP_REQUIEM_OF_SPIRIT, TEXT_WARP_NOCTURNE_OF_SHADOW, TEXT_WARP_PRELUDE_OF_LIGHT,
TEXT_WARP_SERENADE_OF_WATER,
TEXT_WARP_REQUIEM_OF_SPIRIT,
TEXT_WARP_NOCTURNE_OF_SHADOW,
TEXT_WARP_PRELUDE_OF_LIGHT,
}; };
static const int ocarinaSongMap[] = { static const int ocarinaSongMap[] = {
OCARINA_SONG_MINUET, OCARINA_SONG_MINUET, OCARINA_SONG_BOLERO, OCARINA_SONG_SERENADE,
OCARINA_SONG_BOLERO, OCARINA_SONG_REQUIEM, OCARINA_SONG_NOCTURNE, OCARINA_SONG_PRELUDE,
OCARINA_SONG_SERENADE,
OCARINA_SONG_REQUIEM,
OCARINA_SONG_NOCTURNE,
OCARINA_SONG_PRELUDE,
}; };
static const int entranceIndexMap[] = { static const int entranceIndexMap[] = {
@ -32,12 +24,8 @@ static const int entranceIndexMap[] = {
}; };
static const int songAudioMap[] = { static const int songAudioMap[] = {
NA_BGM_OCA_MINUET, NA_BGM_OCA_MINUET, NA_BGM_OCA_BOLERO, NA_BGM_OCA_SERENADE,
NA_BGM_OCA_BOLERO, NA_BGM_OCA_REQUIEM, NA_BGM_OCA_NOCTURNE, NA_BGM_OCA_LIGHT,
NA_BGM_OCA_SERENADE,
NA_BGM_OCA_REQUIEM,
NA_BGM_OCA_NOCTURNE,
NA_BGM_OCA_LIGHT,
}; };
static bool isWarpActive = false; static bool isWarpActive = false;
@ -88,7 +76,8 @@ void PauseWarp_HandleSelection() {
int song = gPlayState->pauseCtx.cursorPoint[PAUSE_QUEST]; int song = gPlayState->pauseCtx.cursorPoint[PAUSE_QUEST];
if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE && if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE &&
gPlayState->pauseCtx.pageIndex == PAUSE_QUEST && gPlayState->pauseCtx.state == 6) { gPlayState->pauseCtx.pageIndex == PAUSE_QUEST && gPlayState->pauseCtx.state == 6) {
if (gSaveContext.ship.quest.id == QUEST_RANDOMIZER && Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS)) { if (gSaveContext.ship.quest.id == QUEST_RANDOMIZER &&
Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS)) {
bool canplay = false; bool canplay = false;
switch (song) { switch (song) {
case QUEST_SONG_MINUET: case QUEST_SONG_MINUET:

View file

@ -5,40 +5,76 @@
namespace CustomMessages { namespace CustomMessages {
using namespace std::literals::string_literals; using namespace std::literals::string_literals;
std::string MESSAGE_END() { return "\x7F\x00"s; } std::string MESSAGE_END() {
std::string WAIT_FOR_INPUT() { return "\x7F\x01"s; } return "\x7F\x00"s;
}
std::string WAIT_FOR_INPUT() {
return "\x7F\x01"s;
}
std::string HORIZONTAL_SPACE(uint8_t x) { std::string HORIZONTAL_SPACE(uint8_t x) {
return "\x7F\x02"s + char(x); return "\x7F\x02"s + char(x);
} }
std::string GO_TO(uint16_t x) { std::string GO_TO(uint16_t x) {
return "\x7F\x03"s + char(x >> 8) + char(x & 0x00FF); return "\x7F\x03"s + char(x >> 8) + char(x & 0x00FF);
} }
std::string INSTANT_TEXT_ON() { return "\x7F\x04"s; } std::string INSTANT_TEXT_ON() {
std::string INSTANT_TEXT_OFF() { return "\x7F\x05"s; } return "\x7F\x04"s;
std::string SHOP_MESSAGE_BOX() { return "\x7F\x06\x00"s; } }
std::string EVENT_TRIGGER() { return "\x7F\x07"s; } std::string INSTANT_TEXT_OFF() {
return "\x7F\x05"s;
}
std::string SHOP_MESSAGE_BOX() {
return "\x7F\x06\x00"s;
}
std::string EVENT_TRIGGER() {
return "\x7F\x07"s;
}
std::string DELAY_FRAMES(uint8_t x) { std::string DELAY_FRAMES(uint8_t x) {
return "\x7F\x08"s + char(x); return "\x7F\x08"s + char(x);
} }
std::string CLOSE_AFTER(uint8_t x) { std::string CLOSE_AFTER(uint8_t x) {
return "\x7F\x0A"s + char(x); return "\x7F\x0A"s + char(x);
} }
std::string PLAYER_NAME() { return "\x7F\x0B"s; } std::string PLAYER_NAME() {
std::string PLAY_OCARINA() { return "\x7F\x0C"s; } return "\x7F\x0B"s;
}
std::string PLAY_OCARINA() {
return "\x7F\x0C"s;
}
std::string ITEM_OBTAINED(uint8_t x) { std::string ITEM_OBTAINED(uint8_t x) {
return "\x7F\x0F"s + char(x); return "\x7F\x0F"s + char(x);
} }
std::string SET_SPEED(uint8_t x) { std::string SET_SPEED(uint8_t x) {
return "\x7F\x10"s + char(x); return "\x7F\x10"s + char(x);
} }
std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"s; } std::string SKULLTULAS_DESTROYED() {
std::string CURRENT_TIME() { return "\x7F\x17"s; } return "\x7F\x15"s;
std::string UNSKIPPABLE() { return "\x7F\x19"s; }
std::string TWO_WAY_CHOICE() { return "\x1B"s; }
std::string NEWLINE() { return "\x7F\x1C"s; }
std::string COLOR(std::string x) { return "\x7F\x1D"s + x; }
std::string CENTER_TEXT() { return "\x7F\x1E"s; }
std::string IF_NOT_MQ() { return "\x7F\x29"s; }
std::string MQ_ELSE() { return "\x7F\x2A"s; }
std::string MQ_END() { return "\x7F\x2B"s; }
} }
std::string CURRENT_TIME() {
return "\x7F\x17"s;
}
std::string UNSKIPPABLE() {
return "\x7F\x19"s;
}
std::string TWO_WAY_CHOICE() {
return "\x1B"s;
}
std::string NEWLINE() {
return "\x7F\x1C"s;
}
std::string COLOR(std::string x) {
return "\x7F\x1D"s + x;
}
std::string CENTER_TEXT() {
return "\x7F\x1E"s;
}
std::string IF_NOT_MQ() {
return "\x7F\x29"s;
}
std::string MQ_ELSE() {
return "\x7F\x2A"s;
}
std::string MQ_END() {
return "\x7F\x2B"s;
}
} // namespace CustomMessages

View file

@ -20,11 +20,10 @@
using namespace Rando; using namespace Rando;
static bool placementFailure = false; static bool placementFailure = false;
PriceSettingsStruct shopsanityPrices = {
PriceSettingsStruct shopsanityPrices = {RSK_SHOPSANITY_PRICES, RSK_SHOPSANITY_PRICES,
RSK_SHOPSANITY_PRICES_FIXED_PRICE, RSK_SHOPSANITY_PRICES_FIXED_PRICE,
RSK_SHOPSANITY_PRICES_RANGE_1, RSK_SHOPSANITY_PRICES_RANGE_1,
RSK_SHOPSANITY_PRICES_RANGE_2, RSK_SHOPSANITY_PRICES_RANGE_2,
@ -33,9 +32,11 @@ PriceSettingsStruct shopsanityPrices = {RSK_SHOPSANITY_PRICES,
RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT, RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT,
RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT, RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT,
RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT, RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT,
RSK_SHOPSANITY_PRICES_AFFORDABLE, }; RSK_SHOPSANITY_PRICES_AFFORDABLE,
};
PriceSettingsStruct scrubPrices = {RSK_SCRUBS_PRICES, PriceSettingsStruct scrubPrices = {
RSK_SCRUBS_PRICES,
RSK_SCRUBS_PRICES_FIXED_PRICE, RSK_SCRUBS_PRICES_FIXED_PRICE,
RSK_SCRUBS_PRICES_RANGE_1, RSK_SCRUBS_PRICES_RANGE_1,
RSK_SCRUBS_PRICES_RANGE_2, RSK_SCRUBS_PRICES_RANGE_2,
@ -44,9 +45,11 @@ PriceSettingsStruct scrubPrices = {RSK_SCRUBS_PRICES,
RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT, RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT,
RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT, RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT,
RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT, RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT,
RSK_SCRUBS_PRICES_AFFORDABLE, }; RSK_SCRUBS_PRICES_AFFORDABLE,
};
PriceSettingsStruct merchantPrices = {RSK_MERCHANT_PRICES, PriceSettingsStruct merchantPrices = {
RSK_MERCHANT_PRICES,
RSK_MERCHANT_PRICES_FIXED_PRICE, RSK_MERCHANT_PRICES_FIXED_PRICE,
RSK_MERCHANT_PRICES_RANGE_1, RSK_MERCHANT_PRICES_RANGE_1,
RSK_MERCHANT_PRICES_RANGE_2, RSK_MERCHANT_PRICES_RANGE_2,
@ -55,7 +58,8 @@ PriceSettingsStruct merchantPrices = {RSK_MERCHANT_PRICES,
RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT, RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT,
RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT, RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT,
RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT, RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT,
RSK_MERCHANT_PRICES_AFFORDABLE, }; RSK_MERCHANT_PRICES_AFFORDABLE,
};
static void RemoveStartingItemsFromPool() { static void RemoveStartingItemsFromPool() {
for (RandomizerGet startingItem : StartingInventory) { for (RandomizerGet startingItem : StartingInventory) {
@ -84,7 +88,9 @@ static void PropagateTimeTravel(GetAccessibleLocationsStruct& gals, RandomizerGe
bool stopOnBeatable = false, bool addToPlaythrough = false) { bool stopOnBeatable = false, bool addToPlaythrough = false) {
// special check for temple of time // special check for temple of time
if (gals.haveTimeAccess && gals.foundTempleOfTime && gals.validatedStartingRegion) { if (gals.haveTimeAccess && gals.foundTempleOfTime && gals.validatedStartingRegion) {
if (!RegionTable(RR_ROOT)->Adult() && RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Child()) { //RANDOTODO: sphere weirdness, other age locations not propagated in this sphere if (!RegionTable(RR_ROOT)->Adult() &&
RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)
->Child()) { // RANDOTODO: sphere weirdness, other age locations not propagated in this sphere
RegionTable(RR_ROOT)->adultDay = RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->childDay; RegionTable(RR_ROOT)->adultDay = RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->childDay;
RegionTable(RR_ROOT)->adultNight = RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->childNight; RegionTable(RR_ROOT)->adultNight = RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->childNight;
ProcessRegion(RegionTable(RR_ROOT), gals, ignore, stopOnBeatable, addToPlaythrough); ProcessRegion(RegionTable(RR_ROOT), gals, ignore, stopOnBeatable, addToPlaythrough);
@ -107,7 +113,8 @@ static bool UpdateToDAccess(Entrance* entrance, Region* connection) {
connection->childDay = true; connection->childDay = true;
ageTimePropogated = true; ageTimePropogated = true;
} }
if (!connection->childNight && parent->childNight && entrance->CheckConditionAtAgeTime(logic->IsChild, logic->AtNight)) { if (!connection->childNight && parent->childNight &&
entrance->CheckConditionAtAgeTime(logic->IsChild, logic->AtNight)) {
connection->childNight = true; connection->childNight = true;
ageTimePropogated = true; ageTimePropogated = true;
} }
@ -115,7 +122,8 @@ static bool UpdateToDAccess(Entrance* entrance, Region* connection) {
connection->adultDay = true; connection->adultDay = true;
ageTimePropogated = true; ageTimePropogated = true;
} }
if (!connection->adultNight && parent->adultNight && entrance->CheckConditionAtAgeTime(logic->IsAdult, logic->AtNight)) { if (!connection->adultNight && parent->adultNight &&
entrance->CheckConditionAtAgeTime(logic->IsAdult, logic->AtNight)) {
connection->adultNight = true; connection->adultNight = true;
ageTimePropogated = true; ageTimePropogated = true;
} }
@ -128,26 +136,32 @@ static bool UpdateToDAccess(Entrance* entrance, Region* connection) {
static void ValidateOtherEntrance(GetAccessibleLocationsStruct& gals) { static void ValidateOtherEntrance(GetAccessibleLocationsStruct& gals) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
// Condition for validating Temple of Time Access // Condition for validating Temple of Time Access
if (!gals.foundTempleOfTime && ((ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD) && RegionTable(RR_TEMPLE_OF_TIME)->Adult()) || if (!gals.foundTempleOfTime &&
((ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD) && RegionTable(RR_TEMPLE_OF_TIME)->Adult()) ||
(ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT) && RegionTable(RR_TEMPLE_OF_TIME)->Child()))) { (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT) && RegionTable(RR_TEMPLE_OF_TIME)->Child()))) {
gals.foundTempleOfTime = true; gals.foundTempleOfTime = true;
} }
// Condition for validating a valid starting region // Condition for validating a valid starting region
if (!gals.validatedStartingRegion) { if (!gals.validatedStartingRegion) {
bool childAccess = ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD) || RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Child(); bool childAccess = ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD) ||
bool adultAccess = ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT) || RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Adult(); RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Child();
bool adultAccess = ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT) ||
RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Adult();
Region* kokiri = RegionTable(RR_KOKIRI_FOREST); Region* kokiri = RegionTable(RR_KOKIRI_FOREST);
Region* kakariko = RegionTable(RR_KAKARIKO_VILLAGE); Region* kakariko = RegionTable(RR_KAKARIKO_VILLAGE);
if ((childAccess && (kokiri->Child() || kakariko->Child())) ||// RANDOTODO when proper ammo logic is done, this could probably be made optional if ((childAccess &&
(kokiri->Child() ||
kakariko->Child())) || // RANDOTODO when proper ammo logic is done, this could probably be made optional
(adultAccess && (kokiri->Adult() || kakariko->Adult()))) { (adultAccess && (kokiri->Adult() || kakariko->Adult()))) {
gals.validatedStartingRegion = true; gals.validatedStartingRegion = true;
ApplyStartingInventory(); // RANDOTODO when proper ammo logic is done, this could be moved to the start ApplyStartingInventory(); // RANDOTODO when proper ammo logic is done, this could be moved to the start
} }
} }
// If we are not shuffling the guard house, add the key so we can properly check for poe merchant access // If we are not shuffling the guard house, add the key so we can properly check for poe merchant access
if (gals.validatedStartingRegion && gals.foundTempleOfTime && !ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL)){ if (gals.validatedStartingRegion && gals.foundTempleOfTime &&
!ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL)) {
Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect(); Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect();
} }
} }
@ -166,7 +180,8 @@ static void ApplyAllAdvancmentItems(){
static void ValidateSphereZero(GetAccessibleLocationsStruct& gals) { static void ValidateSphereZero(GetAccessibleLocationsStruct& gals) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
// Condition for verifying everything required for sphere 0, expanding search to all locations // Condition for verifying everything required for sphere 0, expanding search to all locations
if ((!logic->AreCheckingBigPoes || logic->CanEmptyBigPoes) && gals.validatedStartingRegion && gals.foundTempleOfTime && gals.haveTimeAccess) { if ((!logic->AreCheckingBigPoes || logic->CanEmptyBigPoes) && gals.validatedStartingRegion &&
gals.foundTempleOfTime && gals.haveTimeAccess) {
// stop checking for big poes // stop checking for big poes
logic->AreCheckingBigPoes = false; logic->AreCheckingBigPoes = false;
// Apply all items that are necessary for checking all location access // Apply all items that are necessary for checking all location access
@ -220,13 +235,15 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer
// RANDOTODO Should this match the regular spheres? // RANDOTODO Should this match the regular spheres?
// Add shuffled entrances to the entrance playthrough // Add shuffled entrances to the entrance playthrough
// Include bluewarps when unshuffled but dungeon or boss shuffle is on // Include bluewarps when unshuffled but dungeon or boss shuffle is on
if((exit.IsShuffled() || (exit.GetType() == Rando::EntranceType::BlueWarp && if ((exit.IsShuffled() ||
(exit.GetType() == Rando::EntranceType::BlueWarp &&
(ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_BOSS_ENTRANCES)))) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_BOSS_ENTRANCES)))) &&
!exit.IsAddedToPool() && !ctx->GetEntranceShuffler()->HasNoRandomEntrances()) { !exit.IsAddedToPool() && !ctx->GetEntranceShuffler()->HasNoRandomEntrances()) {
gals.entranceSphere.push_back(&exit); gals.entranceSphere.push_back(&exit);
exit.AddToPool(); exit.AddToPool();
// Don't list a two-way coupled entrance from both directions // Don't list a two-way coupled entrance from both directions
if (exit.GetReverse() != nullptr && exit.GetReplacement()->GetReverse() != nullptr && !exit.IsDecoupled()) { if (exit.GetReverse() != nullptr && exit.GetReplacement()->GetReverse() != nullptr &&
!exit.IsDecoupled()) {
exit.GetReplacement()->GetReverse()->AddToPool(); exit.GetReplacement()->GetReverse()->AddToPool();
} }
} }
@ -234,7 +251,6 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer
} }
} }
// Get the max number of tokens that can possibly be useful // Get the max number of tokens that can possibly be useful
static int GetMaxGSCount() { static int GetMaxGSCount() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
@ -251,7 +267,8 @@ static int GetMaxGSCount() {
// Get the max amount of GS which could be useful from token reward locations // Get the max amount of GS which could be useful from token reward locations
int maxUseful = 0; int maxUseful = 0;
// If the highest advancement item is a token, we know it is useless since it won't lead to an otherwise useful item // If the highest advancement item is a token, we know it is useless since it won't lead to an otherwise useful item
if (ctx->GetItemLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedItem().IsAdvancement() && ctx->GetItemLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedItem().GetItemType() != ITEMTYPE_TOKEN) { if (ctx->GetItemLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedItem().IsAdvancement() &&
ctx->GetItemLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedItem().GetItemType() != ITEMTYPE_TOKEN) {
maxUseful = 100; maxUseful = 100;
} else if (ctx->GetItemLocation(RC_KAK_50_GOLD_SKULLTULA_REWARD)->GetPlacedItem().IsAdvancement() && } else if (ctx->GetItemLocation(RC_KAK_50_GOLD_SKULLTULA_REWARD)->GetPlacedItem().IsAdvancement() &&
ctx->GetItemLocation(RC_KAK_50_GOLD_SKULLTULA_REWARD)->GetPlacedItem().GetItemType() != ITEMTYPE_TOKEN) { ctx->GetItemLocation(RC_KAK_50_GOLD_SKULLTULA_REWARD)->GetPlacedItem().GetItemType() != ITEMTYPE_TOKEN) {
@ -305,7 +322,8 @@ bool IsBombchus(RandomizerGet item, bool includeShops = false){
(includeShops && (item == RG_BUY_BOMBCHUS_10 || item == RG_BUY_BOMBCHUS_20)); (includeShops && (item == RG_BUY_BOMBCHUS_10 || item == RG_BUY_BOMBCHUS_20));
} }
bool IsBeatableWithout(RandomizerCheck excludedCheck, bool replaceItem, RandomizerGet ignore = RG_NONE){ //RANDOTODO make excludCheck an ItemLocation bool IsBeatableWithout(RandomizerCheck excludedCheck, bool replaceItem,
RandomizerGet ignore = RG_NONE) { // RANDOTODO make excludCheck an ItemLocation
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
RandomizerGet copy = ctx->GetItemLocation(excludedCheck)->GetPlacedRandomizerGet(); // Copy out item RandomizerGet copy = ctx->GetItemLocation(excludedCheck)->GetPlacedRandomizerGet(); // Copy out item
ctx->GetItemLocation(excludedCheck)->SetPlacedItem(RG_NONE); // Write in empty item ctx->GetItemLocation(excludedCheck)->SetPlacedItem(RG_NONE); // Write in empty item
@ -348,8 +366,8 @@ void AddToPlaythrough(LocationAccess& locPair, GetAccessibleLocationsStruct& gal
// Decide whether to exclude this location // Decide whether to exclude this location
// This preprocessing is done to reduce the amount of searches performed in PareDownPlaythrough // This preprocessing is done to reduce the amount of searches performed in PareDownPlaythrough
// Want to exclude: // Want to exclude:
//1) Tokens after the last potentially useful one (the last one that gives an advancement item or last for token bridge) // 1) Tokens after the last potentially useful one (the last one that gives an advancement item or last for
//2) Buy items of the same type, after the first (So only see Buy Deku Nut of any amount once) // token bridge) 2) Buy items of the same type, after the first (So only see Buy Deku Nut of any amount once)
bool exclude = true; bool exclude = true;
// Exclude tokens after the last possibly useful one // Exclude tokens after the last possibly useful one
if (type == ITEMTYPE_TOKEN && gals.gsCount < gals.maxGsCount) { if (type == ITEMTYPE_TOKEN && gals.gsCount < gals.maxGsCount) {
@ -395,7 +413,8 @@ void ApplyOrStoreItem(Rando::ItemLocation* loc, GetAccessibleLocationsStruct& ga
} }
// Adds the contents of a location to the current progression and optionally playthrough // Adds the contents of a location to the current progression and optionally playthrough
bool AddCheckToLogic(LocationAccess& locPair, GetAccessibleLocationsStruct& gals, RandomizerGet ignore, bool stopOnBeatable, Region* parentRegion, bool addToPlaythrough=false){ bool AddCheckToLogic(LocationAccess& locPair, GetAccessibleLocationsStruct& gals, RandomizerGet ignore,
bool stopOnBeatable, Region* parentRegion, bool addToPlaythrough = false) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
StartPerformanceTimer(PT_LOCATION_LOGIC); StartPerformanceTimer(PT_LOCATION_LOGIC);
RandomizerCheck loc = locPair.GetLocation(); RandomizerCheck loc = locPair.GetLocation();
@ -426,16 +445,20 @@ bool AddCheckToLogic(LocationAccess& locPair, GetAccessibleLocationsStruct& gals
else if (IsBombchus(ignore) && IsBombchus(locItem, true)) { else if (IsBombchus(ignore) && IsBombchus(locItem, true)) {
ApplyOrStoreItem(location, gals, addToPlaythrough); ApplyOrStoreItem(location, gals, addToPlaythrough);
} }
//We want to ignore a specific Buy item. Buy items with different RandomizerGets are recognised by a shared GetLogicVal // We want to ignore a specific Buy item. Buy items with different RandomizerGets are recognised by a
// shared GetLogicVal
else if (ignore != RG_GOLD_SKULLTULA_TOKEN && IsBombchus(ignore)) { else if (ignore != RG_GOLD_SKULLTULA_TOKEN && IsBombchus(ignore)) {
if ((type == ITEMTYPE_SHOP && Rando::StaticData::GetItemTable()[ignore].GetLogicVal() != location->GetPlacedItem().GetLogicVal()) || type != ITEMTYPE_SHOP) { if ((type == ITEMTYPE_SHOP && Rando::StaticData::GetItemTable()[ignore].GetLogicVal() !=
location->GetPlacedItem().GetLogicVal()) ||
type != ITEMTYPE_SHOP) {
ApplyOrStoreItem(location, gals, addToPlaythrough); ApplyOrStoreItem(location, gals, addToPlaythrough);
} }
} }
} }
// If it doesn't, we can just add the location // If it doesn't, we can just add the location
else { else {
ApplyOrStoreItem(location, gals, addToPlaythrough); //Add item to cache to be considered in logic next iteration ApplyOrStoreItem(location, gals,
addToPlaythrough); // Add item to cache to be considered in logic next iteration
} }
} }
if (addToPlaythrough) { if (addToPlaythrough) {
@ -451,8 +474,8 @@ bool AddCheckToLogic(LocationAccess& locPair, GetAccessibleLocationsStruct& gals
return false; return false;
} }
void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, RandomizerGet ignore, void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, RandomizerGet ignore, bool stopOnBeatable,
bool stopOnBeatable, bool addToPlaythrough){ bool addToPlaythrough) {
if (gals.haveTimeAccess) { if (gals.haveTimeAccess) {
region->ApplyTimePass(); region->ApplyTimePass();
@ -477,8 +500,7 @@ void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, Randomize
} }
} }
// Condition for validating that all startring AgeTimes have timepass access // Condition for validating that all startring AgeTimes have timepass access
if (gals.timePassChildDay && gals.timePassChildNight && if (gals.timePassChildDay && gals.timePassChildNight && gals.timePassAdultDay && gals.timePassAdultNight) {
gals.timePassAdultDay && gals.timePassAdultNight) {
gals.haveTimeAccess = true; gals.haveTimeAccess = true;
region->ApplyTimePass(); region->ApplyTimePass();
} }
@ -504,7 +526,9 @@ void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, Randomize
} }
// Return any of the targetLocations that are accessible in logic // Return any of the targetLocations that are accessible in logic
std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& targetLocations, RandomizerGet ignore /* = RG_NONE*/, bool calculatingAvailableChecks /* = false */) { std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& targetLocations,
RandomizerGet ignore /* = RG_NONE*/,
bool calculatingAvailableChecks /* = false */) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
GetAccessibleLocationsStruct gals(0); GetAccessibleLocationsStruct gals(0);
gals.calculatingAvailableChecks = calculatingAvailableChecks; gals.calculatingAvailableChecks = calculatingAvailableChecks;
@ -618,7 +642,8 @@ void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAcce
for (const RandomizerCheck loc : ctx->allLocations) { for (const RandomizerCheck loc : ctx->allLocations) {
if (!ctx->GetItemLocation(loc)->IsAddedToPool()) { if (!ctx->GetItemLocation(loc)->IsAddedToPool()) {
ctx->allLocationsReachable = false; ctx->allLocationsReachable = false;
auto message = "Location " + auto message =
"Location " +
Rando::StaticData::GetLocation(ctx->GetItemLocation(loc)->GetRandomizerCheck())->GetName() + Rando::StaticData::GetLocation(ctx->GetItemLocation(loc)->GetRandomizerCheck())->GetName() +
" not reachable\n"; " not reachable\n";
LUSLOG_DEBUG("%s", message.c_str()); LUSLOG_DEBUG("%s", message.c_str());
@ -630,7 +655,8 @@ void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAcce
} }
} }
void LookForExternalArea(Region* currentRegion, std::set<Region*> &alreadyChecked, std::set<RandomizerArea> &areas, bool LowPriorityMode=false){ void LookForExternalArea(Region* currentRegion, std::set<Region*>& alreadyChecked, std::set<RandomizerArea>& areas,
bool LowPriorityMode = false) {
for (const auto& entrance : currentRegion->entrances) { for (const auto& entrance : currentRegion->entrances) {
// if the region is arealess and hasn't already been checked, recursivly check what connects to it // if the region is arealess and hasn't already been checked, recursivly check what connects to it
// if this entrance does not pass areas, only process it if we are in low priority mode // if this entrance does not pass areas, only process it if we are in low priority mode
@ -641,7 +667,8 @@ void LookForExternalArea(Region* currentRegion, std::set<Region*> &alreadyChecke
LookForExternalArea(entrance->GetParentRegion(), alreadyChecked, areas, LowPriorityMode); LookForExternalArea(entrance->GetParentRegion(), alreadyChecked, areas, LowPriorityMode);
// If we find a valid area we should add it. // If we find a valid area we should add it.
// If it's Links Pocket or RA_NONE, do not propagate those, they are not real areas. // If it's Links Pocket or RA_NONE, do not propagate those, they are not real areas.
//This check is likely to fail if a region somehow is both in Link's Pocket and elsewhere, but this should never happen // This check is likely to fail if a region somehow is both in Link's Pocket and elsewhere, but this
// should never happen
} else if (*otherAreas.begin() > RA_LINKS_POCKET) { } else if (*otherAreas.begin() > RA_LINKS_POCKET) {
areas.merge(otherAreas); areas.merge(otherAreas);
} }
@ -692,8 +719,8 @@ static void PareDownPlaythrough() {
RandomizerGet locGet = ctx->GetItemLocation(loc)->GetPlacedRandomizerGet(); // Copy out item RandomizerGet locGet = ctx->GetItemLocation(loc)->GetPlacedRandomizerGet(); // Copy out item
RandomizerGet ignore = RG_NONE; RandomizerGet ignore = RG_NONE;
if (locGet == RG_GOLD_SKULLTULA_TOKEN || IsBombchus(locGet, true) if (locGet == RG_GOLD_SKULLTULA_TOKEN || IsBombchus(locGet, true) ||
|| Rando::StaticData::RetrieveItem(locGet).GetItemType() == ITEMTYPE_SHOP) { Rando::StaticData::RetrieveItem(locGet).GetItemType() == ITEMTYPE_SHOP) {
ignore = locGet; ignore = locGet;
} }
@ -702,8 +729,7 @@ static void PareDownPlaythrough() {
ctx->playthroughLocations[i].erase(ctx->playthroughLocations[i].begin() + j); ctx->playthroughLocations[i].erase(ctx->playthroughLocations[i].begin() + j);
ctx->GetItemLocation(loc)->SetDelayedItem(locGet); // Game is still beatable, don't add back until later ctx->GetItemLocation(loc)->SetDelayedItem(locGet); // Game is still beatable, don't add back until later
toAddBackItem.push_back(loc); toAddBackItem.push_back(loc);
} } else {
else {
ctx->GetItemLocation(loc)->SetPlacedItem(locGet); // Immediately put item back so game is beatable again ctx->GetItemLocation(loc)->SetPlacedItem(locGet); // Immediately put item back so game is beatable again
} }
} }
@ -731,8 +757,8 @@ static void CalculateWotH() {
// size - 1 so Triforce is not counted // size - 1 so Triforce is not counted
for (size_t i = 0; i < ctx->playthroughLocations.size() - 1; i++) { for (size_t i = 0; i < ctx->playthroughLocations.size() - 1; i++) {
for (size_t j = 0; j < ctx->playthroughLocations[i].size(); j++) { for (size_t j = 0; j < ctx->playthroughLocations[i].size(); j++) {
//If removing this item and no other item caused the game to become unbeatable, then it is strictly necessary, // If removing this item and no other item caused the game to become unbeatable, then it is strictly
//so add it unless it is in Links Pocket or an isolated place. // necessary, so add it unless it is in Links Pocket or an isolated place.
auto itemLoc = ctx->GetItemLocation(ctx->playthroughLocations[i][j]); auto itemLoc = ctx->GetItemLocation(ctx->playthroughLocations[i][j]);
if (itemLoc->IsHintable() && itemLoc->GetFirstArea() > RA_LINKS_POCKET && if (itemLoc->IsHintable() && itemLoc->GetFirstArea() > RA_LINKS_POCKET &&
!(IsBeatableWithout(ctx->playthroughLocations[i][j], true))) { !(IsBeatableWithout(ctx->playthroughLocations[i][j], true))) {
@ -758,7 +784,8 @@ static bool FindIfBarren(Rando::ItemLocation* itemLoc, std::array<bool, RA_MAX>
// Calculate barren locations and assign Barren Candidacy to all locations inside those areas // Calculate barren locations and assign Barren Candidacy to all locations inside those areas
static void CalculateBarren() { static void CalculateBarren() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
std::array<bool, RA_MAX> NotBarren = {}; //I would invert this but the "initialise all as true" syntax wasn't working std::array<bool, RA_MAX>
NotBarren = {}; // I would invert this but the "initialise all as true" syntax wasn't working
// Isolated Areas and Link's Pocket are never Hinted Barren // Isolated Areas and Link's Pocket are never Hinted Barren
NotBarren[RA_NONE] = true; NotBarren[RA_NONE] = true;
NotBarren[RA_LINKS_POCKET] = true; NotBarren[RA_LINKS_POCKET] = true;
@ -783,7 +810,8 @@ static void CalculateBarren() {
} }
// Will place things completely randomly, no logic checks are performed // Will place things completely randomly, no logic checks are performed
static void FastFill(std::vector<RandomizerGet> items, std::vector<RandomizerCheck> locations, bool endOnItemsEmpty = false) { static void FastFill(std::vector<RandomizerGet> items, std::vector<RandomizerCheck> locations,
bool endOnItemsEmpty = false) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
// Loop until locations are empty, or also end if items are empty and the parameters specify to end then // Loop until locations are empty, or also end if items are empty and the parameters specify to end then
while (!locations.empty() && (!endOnItemsEmpty || !items.empty())) { while (!locations.empty() && (!endOnItemsEmpty || !items.empty())) {
@ -934,11 +962,16 @@ static void RandomizeDungeonRewards() {
int baseOffset = Rando::StaticData::RetrieveItem(RG_KOKIRI_EMERALD).GetItemID(); int baseOffset = Rando::StaticData::RetrieveItem(RG_KOKIRI_EMERALD).GetItemID();
// End of Dungeons includes Link's Pocket // End of Dungeons includes Link's Pocket
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)) { 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)) {
// get stones and medallions // get stones and medallions
std::vector<RandomizerGet> rewards = FilterAndEraseFromPool(ItemPool, [](const auto i) {return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;}); std::vector<RandomizerGet> rewards = FilterAndEraseFromPool(ItemPool, [](const auto i) {
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
});
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { // Place dungeon rewards in vanilla locations if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA) ||
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS)
.Is(RO_DUNGEON_REWARDS_VANILLA)) { // Place dungeon rewards in vanilla locations
for (RandomizerCheck loc : Rando::StaticData::dungeonRewardLocations) { for (RandomizerCheck loc : Rando::StaticData::dungeonRewardLocations) {
ctx->GetItemLocation(loc)->PlaceVanillaItem(); ctx->GetItemLocation(loc)->PlaceVanillaItem();
} }
@ -955,8 +988,9 @@ static void RandomizeDungeonRewards() {
} }
} else if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_DUNGEON_REWARD)) { } else if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_DUNGEON_REWARD)) {
// get 1 stone/medallion // get 1 stone/medallion
std::vector<RandomizerGet> rewards = FilterFromPool( std::vector<RandomizerGet> rewards = FilterFromPool(ItemPool, [](const auto i) {
ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD; }); return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
});
// If there are no remaining stones/medallions, then Link's pocket won't get one // If there are no remaining stones/medallions, then Link's pocket won't get one
if (rewards.empty()) { if (rewards.empty()) {
ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE); ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE);
@ -964,7 +998,8 @@ static void RandomizeDungeonRewards() {
} }
RandomizerGet startingReward = RandomElement(rewards, true); RandomizerGet startingReward = RandomElement(rewards, true);
//LinksPocketRewardBitMask = bitMaskTable[Rando::StaticData::RetrieveItem(startingReward).GetItemID() - baseOffset]; // LinksPocketRewardBitMask = bitMaskTable[Rando::StaticData::RetrieveItem(startingReward).GetItemID() -
// baseOffset];
ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingReward); ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingReward);
// erase the stone/medallion from the Item Pool // erase the stone/medallion from the Item Pool
FilterAndEraseFromPool(ItemPool, [startingReward](const RandomizerGet i) { return i == startingReward; }); FilterAndEraseFromPool(ItemPool, [startingReward](const RandomizerGet i) { return i == startingReward; });
@ -976,9 +1011,8 @@ static void RandomizeDungeonRewards() {
static void FillExcludedLocations() { static void FillExcludedLocations() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
// Only fill in excluded locations that don't already have something and are forbidden // Only fill in excluded locations that don't already have something and are forbidden
std::vector<RandomizerCheck> excludedLocations = FilterFromPool(ctx->allLocations, [ctx](const auto loc){ std::vector<RandomizerCheck> excludedLocations =
return ctx->GetItemLocation(loc)->IsExcluded(); FilterFromPool(ctx->allLocations, [ctx](const auto loc) { return ctx->GetItemLocation(loc)->IsExcluded(); });
});
for (RandomizerCheck loc : excludedLocations) { for (RandomizerCheck loc : excludedLocations) {
PlaceJunkInExcludedLocation(loc); PlaceJunkInExcludedLocation(loc);
@ -1004,21 +1038,26 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) {
} }
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_DUNGEON_REWARDS)) { if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_DUNGEON_REWARDS)) {
return !(Rando::StaticData::GetLocation(loc)->GetRCType() == RCTYPE_BOSS_HEART_OR_OTHER_REWARD || return !(Rando::StaticData::GetLocation(loc)->GetRCType() == RCTYPE_BOSS_HEART_OR_OTHER_REWARD ||
loc == RC_SHEIK_IN_ICE_CAVERN || loc == RC_SHEIK_IN_ICE_CAVERN || loc == RC_SONG_FROM_IMPA);
loc == RC_SONG_FROM_IMPA);
} }
return true; return true;
}); });
// Add specific items that need be randomized within this dungeon // Add specific items that need be randomized within this dungeon
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetSmallKey() != RG_NONE) { if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetSmallKey() != RG_NONE) {
std::vector<RandomizerGet> dungeonSmallKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());}); std::vector<RandomizerGet> dungeonSmallKeys =
FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());
});
AddElementsToPool(dungeonItems, dungeonSmallKeys); AddElementsToPool(dungeonItems, dungeonSmallKeys);
} }
if ((ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) || if ((ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) &&
(ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON) && dungeon->GetBossKey() == RG_GANONS_CASTLE_BOSS_KEY)) { dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) ||
auto dungeonBossKey = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return i == dungeon->GetBossKey();}); (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON) &&
dungeon->GetBossKey() == RG_GANONS_CASTLE_BOSS_KEY)) {
auto dungeonBossKey =
FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); });
AddElementsToPool(dungeonItems, dungeonBossKey); AddElementsToPool(dungeonItems, dungeonBossKey);
} }
@ -1026,8 +1065,11 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) {
AssumedFill(dungeonItems, dungeonLocations); AssumedFill(dungeonItems, dungeonLocations);
// randomize map and compass separately since they're not progressive // randomize map and compass separately since they're not progressive
if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetMap() != RG_NONE && dungeon->GetCompass() != RG_NONE) { if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetMap() != RG_NONE &&
auto dungeonMapAndCompass = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return i == dungeon->GetMap() || i == dungeon->GetCompass();}); dungeon->GetCompass() != RG_NONE) {
auto dungeonMapAndCompass = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
return i == dungeon->GetMap() || i == dungeon->GetCompass();
});
AssumedFill(dungeonMapAndCompass, dungeonLocations); AssumedFill(dungeonMapAndCompass, dungeonLocations);
} }
} }
@ -1052,45 +1094,61 @@ static void RandomizeDungeonItems() {
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) { if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) {
auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());}); auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());
});
AddElementsToPool(anyDungeonItems, dungeonKeys); AddElementsToPool(anyDungeonItems, dungeonKeys);
} else if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) { } else if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());}); auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());
});
AddElementsToPool(overworldItems, dungeonKeys); AddElementsToPool(overworldItems, dungeonKeys);
} }
if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) { if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) &&
auto bossKey = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetBossKey();}); dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) {
auto bossKey = FilterAndEraseFromPool(
ItemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); });
AddElementsToPool(anyDungeonItems, bossKey); AddElementsToPool(anyDungeonItems, bossKey);
} else if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) { } else if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) &&
auto bossKey = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetBossKey();}); dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) {
auto bossKey = FilterAndEraseFromPool(
ItemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); });
AddElementsToPool(overworldItems, bossKey); AddElementsToPool(overworldItems, bossKey);
} }
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) { if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) {
auto ganonBossKey = FilterAndEraseFromPool(ItemPool, [](const auto i){return i == RG_GANONS_CASTLE_BOSS_KEY;}); auto ganonBossKey =
FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; });
AddElementsToPool(anyDungeonItems, ganonBossKey); AddElementsToPool(anyDungeonItems, ganonBossKey);
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) { } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) {
auto ganonBossKey = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; }); auto ganonBossKey =
FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; });
AddElementsToPool(overworldItems, ganonBossKey); AddElementsToPool(overworldItems, ganonBossKey);
} }
} }
if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_ANY_DUNGEON)) { if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_ANY_DUNGEON)) {
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_HIDEOUT_SMALL_KEY || i == RG_HIDEOUT_KEY_RING; }); auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) {
return i == RG_HIDEOUT_SMALL_KEY || i == RG_HIDEOUT_KEY_RING;
});
AddElementsToPool(anyDungeonItems, gerudoKeys); AddElementsToPool(anyDungeonItems, gerudoKeys);
} else if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_OVERWORLD)) { } else if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_OVERWORLD)) {
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_HIDEOUT_SMALL_KEY || i == RG_HIDEOUT_KEY_RING; }); auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) {
return i == RG_HIDEOUT_SMALL_KEY || i == RG_HIDEOUT_KEY_RING;
});
AddElementsToPool(overworldItems, gerudoKeys); AddElementsToPool(overworldItems, gerudoKeys);
} }
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_ANY_DUNGEON)) { if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_ANY_DUNGEON)) {
auto rewards = FilterAndEraseFromPool( auto rewards = FilterAndEraseFromPool(ItemPool, [](const auto i) {
ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD; }); return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
});
AddElementsToPool(anyDungeonItems, rewards); AddElementsToPool(anyDungeonItems, rewards);
} else if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_OVERWORLD)) { } else if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_OVERWORLD)) {
auto rewards = FilterAndEraseFromPool( auto rewards = FilterAndEraseFromPool(ItemPool, [](const auto i) {
ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD; }); return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
});
AddElementsToPool(overworldItems, rewards); AddElementsToPool(overworldItems, rewards);
} }
@ -1101,10 +1159,14 @@ static void RandomizeDungeonItems() {
// Randomize maps and compasses after since they're not advancement items // Randomize maps and compasses after since they're not advancement items
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) { if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) {
auto mapAndCompassItems = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetMap() || i == dungeon->GetCompass();}); auto mapAndCompassItems = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
return i == dungeon->GetMap() || i == dungeon->GetCompass();
});
AssumedFill(mapAndCompassItems, anyDungeonLocations, true); AssumedFill(mapAndCompassItems, anyDungeonLocations, true);
} else if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) { } else if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
auto mapAndCompassItems = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetMap() || i == dungeon->GetCompass();}); auto mapAndCompassItems = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
return i == dungeon->GetMap() || i == dungeon->GetCompass();
});
AssumedFill(mapAndCompassItems, ctx->overworldLocations, true); AssumedFill(mapAndCompassItems, ctx->overworldLocations, true);
} }
} }
@ -1115,7 +1177,8 @@ static void RandomizeLinksPocket() {
if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_ADVANCEMENT)) { if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_ADVANCEMENT)) {
// Get all the advancement items don't include tokens // Get all the advancement items don't include tokens
std::vector<RandomizerGet> advancementItems = FilterAndEraseFromPool(ItemPool, [](const auto i) { std::vector<RandomizerGet> advancementItems = FilterAndEraseFromPool(ItemPool, [](const auto i) {
return Rando::StaticData::RetrieveItem(i).IsAdvancement() && Rando::StaticData::RetrieveItem(i).GetItemType() != ITEMTYPE_TOKEN; return Rando::StaticData::RetrieveItem(i).IsAdvancement() &&
Rando::StaticData::RetrieveItem(i).GetItemType() != ITEMTYPE_TOKEN;
}); });
// select a random one // select a random one
RandomizerGet startingItem = RandomElement(advancementItems, true); RandomizerGet startingItem = RandomElement(advancementItems, true);
@ -1190,7 +1253,9 @@ int Fill() {
} }
SetAreas(); SetAreas();
// erase temporary shop items // erase temporary shop items
FilterAndEraseFromPool(ItemPool, [](const auto item) { return Rando::StaticData::RetrieveItem(item).GetItemType() == ITEMTYPE_SHOP; }); FilterAndEraseFromPool(ItemPool, [](const auto item) {
return Rando::StaticData::RetrieveItem(item).GetItemType() == ITEMTYPE_SHOP;
});
StopPerformanceTimer(PT_ENTRANCE_SHUFFLE); StopPerformanceTimer(PT_ENTRANCE_SHUFFLE);
// ctx->showItemProgress = true; // ctx->showItemProgress = true;
@ -1203,7 +1268,8 @@ int Fill() {
} else { } else {
SPDLOG_INFO("Shuffling Shop Items"); SPDLOG_INFO("Shuffling Shop Items");
int total_replaced = 0; int total_replaced = 0;
if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_RANDOM) || ctx->GetOption(RSK_SHOPSANITY_COUNT).IsNot(RO_SHOPSANITY_COUNT_ZERO_ITEMS)) { //Shopsanity 1-7, random if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_RANDOM) ||
ctx->GetOption(RSK_SHOPSANITY_COUNT).IsNot(RO_SHOPSANITY_COUNT_ZERO_ITEMS)) { // Shopsanity 1-7, random
/* /*
Indices from OoTR. So shopsanity one will overwrite 7, three will overwrite 7, 5, 8, etc. Indices from OoTR. So shopsanity one will overwrite 7, three will overwrite 7, 5, 8, etc.
8 6 2 4 8 6 2 4
@ -1213,11 +1279,13 @@ int Fill() {
// Overwrite appropriate number of shop items // Overwrite appropriate number of shop items
#define LOCATIONS_PER_SHOP 8 #define LOCATIONS_PER_SHOP 8
for (size_t i = 0; i < Rando::StaticData::GetShopLocations().size() / LOCATIONS_PER_SHOP; i++) { for (size_t i = 0; i < Rando::StaticData::GetShopLocations().size() / LOCATIONS_PER_SHOP; i++) {
int num_to_replace = GetShopsanityReplaceAmount(); //1-7 shop items will be overwritten, depending on settings int num_to_replace =
GetShopsanityReplaceAmount(); // 1-7 shop items will be overwritten, depending on settings
total_replaced += num_to_replace; total_replaced += num_to_replace;
for (int j = 0; j < num_to_replace; j++) { for (int j = 0; j < num_to_replace; j++) {
int itemindex = indices[j]; int itemindex = indices[j];
RandomizerCheck rc = Rando::StaticData::GetShopLocations()[i * LOCATIONS_PER_SHOP + itemindex - 1]; RandomizerCheck rc =
Rando::StaticData::GetShopLocations()[i * LOCATIONS_PER_SHOP + itemindex - 1];
Rando::ItemLocation* itemLoc = ctx->GetItemLocation(rc); Rando::ItemLocation* itemLoc = ctx->GetItemLocation(rc);
uint16_t shopsanityPrice = GetRandomPrice(Rando::StaticData::GetLocation(rc), shopsanityPrices); uint16_t shopsanityPrice = GetRandomPrice(Rando::StaticData::GetLocation(rc), shopsanityPrices);
itemLoc->SetCustomPrice(shopsanityPrice); itemLoc->SetCustomPrice(shopsanityPrice);
@ -1244,28 +1312,25 @@ int Fill() {
auto scrubLoc = Rando::StaticData::GetScrubLocations(); auto scrubLoc = Rando::StaticData::GetScrubLocations();
if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_ALL)) { if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_ALL)) {
for (size_t i = 0; i < scrubLoc.size(); i++) { for (size_t i = 0; i < scrubLoc.size(); i++) {
ctx->GetItemLocation(scrubLoc[i])->SetCustomPrice( ctx->GetItemLocation(scrubLoc[i])
GetRandomPrice(Rando::StaticData::GetLocation(scrubLoc[i]), scrubPrices) ->SetCustomPrice(GetRandomPrice(Rando::StaticData::GetLocation(scrubLoc[i]), scrubPrices));
);
} }
} else { } else {
for (size_t i = 0; i < scrubLoc.size(); i++) { for (size_t i = 0; i < scrubLoc.size(); i++) {
ctx->GetItemLocation(scrubLoc[i])->SetCustomPrice( ctx->GetItemLocation(scrubLoc[i])
Rando::StaticData::GetLocation(scrubLoc[i])->GetVanillaPrice() ->SetCustomPrice(Rando::StaticData::GetLocation(scrubLoc[i])->GetVanillaPrice());
);
} }
} }
// set merchant prices // set merchant prices
if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) ||
ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)) { ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)) {
ctx->GetItemLocation(RC_ZR_MAGIC_BEAN_SALESMAN)->SetCustomPrice( ctx->GetItemLocation(RC_ZR_MAGIC_BEAN_SALESMAN)
GetRandomPrice(Rando::StaticData::GetLocation(RC_ZR_MAGIC_BEAN_SALESMAN), merchantPrices) ->SetCustomPrice(
); GetRandomPrice(Rando::StaticData::GetLocation(RC_ZR_MAGIC_BEAN_SALESMAN), merchantPrices));
} else { } else {
ctx->GetItemLocation(RC_ZR_MAGIC_BEAN_SALESMAN)->SetCustomPrice( ctx->GetItemLocation(RC_ZR_MAGIC_BEAN_SALESMAN)
Rando::StaticData::GetLocation(RC_ZR_MAGIC_BEAN_SALESMAN)->GetVanillaPrice() ->SetCustomPrice(Rando::StaticData::GetLocation(RC_ZR_MAGIC_BEAN_SALESMAN)->GetVanillaPrice());
);
} }
auto merchantLoc = Rando::StaticData::GetMerchantLocations(); auto merchantLoc = Rando::StaticData::GetMerchantLocations();
@ -1273,15 +1338,13 @@ int Fill() {
if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) ||
ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)) { ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)) {
for (size_t i = 0; i < merchantLoc.size(); i++) { for (size_t i = 0; i < merchantLoc.size(); i++) {
ctx->GetItemLocation(merchantLoc[i])->SetCustomPrice( ctx->GetItemLocation(merchantLoc[i])
GetRandomPrice(Rando::StaticData::GetLocation(merchantLoc[i]), merchantPrices) ->SetCustomPrice(GetRandomPrice(Rando::StaticData::GetLocation(merchantLoc[i]), merchantPrices));
);
} }
} else { } else {
for (size_t i = 0; i < merchantLoc.size(); i++) { for (size_t i = 0; i < merchantLoc.size(); i++) {
ctx->GetItemLocation(merchantLoc[i])->SetCustomPrice( ctx->GetItemLocation(merchantLoc[i])
Rando::StaticData::GetLocation(merchantLoc[i])->GetVanillaPrice() ->SetCustomPrice(Rando::StaticData::GetLocation(merchantLoc[i])->GetVanillaPrice());
);
} }
} }
StopPerformanceTimer(PT_SHOPSANITY); StopPerformanceTimer(PT_SHOPSANITY);
@ -1302,20 +1365,21 @@ int Fill() {
if (ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_ANYWHERE)) { if (ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_ANYWHERE)) {
// Get each song // Get each song
std::vector<RandomizerGet> songs = FilterAndEraseFromPool( std::vector<RandomizerGet> songs = FilterAndEraseFromPool(ItemPool, [](const auto i) {
ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_SONG; }); return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_SONG;
});
// Get each song location // Get each song location
std::vector<RandomizerCheck> songLocations; std::vector<RandomizerCheck> songLocations;
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_SONG_LOCATIONS)) { if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_SONG_LOCATIONS)) {
songLocations = FilterFromPool( songLocations = FilterFromPool(ctx->allLocations, [](const auto loc) {
ctx->allLocations, [](const auto loc) { return Rando::StaticData::GetLocation(loc)->GetRCType() == RCTYPE_SONG_LOCATION; }); return Rando::StaticData::GetLocation(loc)->GetRCType() == RCTYPE_SONG_LOCATION;
});
} else if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_DUNGEON_REWARDS)) { } else if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_DUNGEON_REWARDS)) {
songLocations = FilterFromPool(ctx->allLocations, [](const auto loc) { songLocations = FilterFromPool(ctx->allLocations, [](const auto loc) {
return Rando::StaticData::GetLocation(loc)->GetRCType() == RCTYPE_BOSS_HEART_OR_OTHER_REWARD || return Rando::StaticData::GetLocation(loc)->GetRCType() == RCTYPE_BOSS_HEART_OR_OTHER_REWARD ||
loc == RC_SHEIK_IN_ICE_CAVERN || loc == RC_SHEIK_IN_ICE_CAVERN || loc == RC_SONG_FROM_IMPA;
loc == RC_SONG_FROM_IMPA;
}); });
} }
@ -1330,12 +1394,11 @@ int Fill() {
RandomizeLinksPocket(); RandomizeLinksPocket();
StopPerformanceTimer(PT_LIMITED_CHECKS); StopPerformanceTimer(PT_LIMITED_CHECKS);
StartPerformanceTimer(PT_ADVANCEMENT_ITEMS); StartPerformanceTimer(PT_ADVANCEMENT_ITEMS);
SPDLOG_INFO("Shuffling Advancement Items"); SPDLOG_INFO("Shuffling Advancement Items");
// Then place the rest of the advancement items // Then place the rest of the advancement items
std::vector<RandomizerGet> remainingAdvancementItems = std::vector<RandomizerGet> remainingAdvancementItems = FilterAndEraseFromPool(
FilterAndEraseFromPool(ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); }); ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); });
AssumedFill(remainingAdvancementItems, ctx->allLocations, true); AssumedFill(remainingAdvancementItems, ctx->allLocations, true);
StopPerformanceTimer(PT_ADVANCEMENT_ITEMS); StopPerformanceTimer(PT_ADVANCEMENT_ITEMS);
@ -1346,7 +1409,6 @@ int Fill() {
FastFill(remainingPool, GetAllEmptyLocations(), false); FastFill(remainingPool, GetAllEmptyLocations(), false);
StopPerformanceTimer(PT_REMAINING_ITEMS); StopPerformanceTimer(PT_REMAINING_ITEMS);
StartPerformanceTimer(PT_PLAYTHROUGH_GENERATION); StartPerformanceTimer(PT_PLAYTHROUGH_GENERATION);
GeneratePlaythrough(); GeneratePlaythrough();
StopPerformanceTimer(PT_PLAYTHROUGH_GENERATION); StopPerformanceTimer(PT_PLAYTHROUGH_GENERATION);

View file

@ -2417,4 +2417,4 @@ void StaticData::HintTable_Init() {
// clang-format on // clang-format on
} }
} } // namespace Rando

View file

@ -2227,4 +2227,4 @@ void StaticData::HintTable_Init_Exclude_Dungeon() {
// clang-format on // clang-format on
} }
} } // namespace Rando

View file

@ -2017,4 +2017,4 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
// clang-format on // clang-format on
} }
} } // namespace Rando

View file

@ -2987,4 +2987,4 @@ void StaticData::HintTable_Init_Item() {
// clang-format on // clang-format on
} }
} } // namespace Rando

View file

@ -15,12 +15,8 @@
using namespace Rando; using namespace Rando;
HintDistributionSetting::HintDistributionSetting(std::string _name, HintDistributionSetting::HintDistributionSetting(std::string _name, HintType _type, uint32_t _weight, uint8_t _fixed,
HintType _type, uint8_t _copies, std::function<bool(RandomizerCheck)> _filter,
uint32_t _weight,
uint8_t _fixed,
uint8_t _copies,
std::function<bool(RandomizerCheck)> _filter,
uint8_t _dungeonLimit) { uint8_t _dungeonLimit) {
name = _name; name = _name;
type = _type; type = _type;
@ -32,8 +28,10 @@ HintDistributionSetting::HintDistributionSetting(std::string _name,
} }
//RANDOTODO rearrange once all HintText's have names //RANDOTODO rearrange once all HintText's have names
HintText::HintText(CustomMessage clearText_, std::vector<CustomMessage> ambiguousText_, std::vector<CustomMessage> obscureText_, CustomMessage name_) HintText::HintText(CustomMessage clearText_, std::vector<CustomMessage> ambiguousText_,
: clearText(std::move(clearText_)), ambiguousText(std::move(ambiguousText_)), obscureText(std::move(obscureText_)), name(std::move(name_)){} std::vector<CustomMessage> obscureText_, CustomMessage name_)
: clearText(std::move(clearText_)), ambiguousText(std::move(ambiguousText_)), obscureText(std::move(obscureText_)), name(std::move(name_)) {
}
const CustomMessage& HintText::GetClear() const { const CustomMessage& HintText::GetClear() const {
return clearText; return clearText;
@ -100,20 +98,20 @@ const CustomMessage HintText::GetMessageCopy() const {
} }
bool HintText::operator==(const HintText& right) const { bool HintText::operator==(const HintText& right) const {
return obscureText == right.obscureText && return obscureText == right.obscureText && ambiguousText == right.ambiguousText && clearText == right.clearText;
ambiguousText == right.ambiguousText &&
clearText == right.clearText;
} }
bool HintText::operator!=(const HintText& right) const { bool HintText::operator!=(const HintText& right) const {
return !operator==(right); return !operator==(right);
} }
StaticHintInfo::StaticHintInfo(HintType _type, std::vector<RandomizerHintTextKey> _hintKeys, RandomizerSettingKey _setting, StaticHintInfo::StaticHintInfo(HintType _type, std::vector<RandomizerHintTextKey> _hintKeys,
std::variant<bool, uint8_t> _condition, std::vector<RandomizerCheck> _targetChecks, RandomizerSettingKey _setting, std::variant<bool, uint8_t> _condition,
std::vector<RandomizerGet> _targetItems, std::vector<RandomizerCheck> _hintChecks, bool _yourPocket, int _num): std::vector<RandomizerCheck> _targetChecks, std::vector<RandomizerGet> _targetItems,
type(_type), hintKeys(_hintKeys), setting(_setting), condition(_condition), targetChecks(_targetChecks), std::vector<RandomizerCheck> _hintChecks, bool _yourPocket, int _num)
targetItems(_targetItems), hintChecks(_hintChecks), yourPocket(_yourPocket), num(_num){} : type(_type), hintKeys(_hintKeys), setting(_setting), condition(_condition), targetChecks(_targetChecks),
targetItems(_targetItems), hintChecks(_hintChecks), yourPocket(_yourPocket), num(_num) {
}
RandomizerHintTextKey GetRandomJunkHint() { RandomizerHintTextKey GetRandomJunkHint() {
// Temp code to handle random junk hints now I work in keys instead of a vector of HintText // Temp code to handle random junk hints now I work in keys instead of a vector of HintText
@ -127,7 +125,6 @@ RandomizerHintTextKey GetRandomGanonJoke(){
return (RandomizerHintTextKey)(Random(0, range) + RHT_GANON_JOKE01); return (RandomizerHintTextKey)(Random(0, range) + RHT_GANON_JOKE01);
} }
bool FilterWotHLocations(RandomizerCheck loc) { bool FilterWotHLocations(RandomizerCheck loc) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return ctx->GetItemLocation(loc)->IsWothCandidate(); return ctx->GetItemLocation(loc)->IsWothCandidate();
@ -229,7 +226,8 @@ uint8_t StonesRequiredBySettings() {
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get(); stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get();
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get() - 6; stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get() - 6;
} else if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) { } else if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) &&
(ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) {
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 6; stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 6;
} }
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
@ -249,14 +247,16 @@ uint8_t MedallionsRequiredBySettings() {
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get(); medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get();
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get() - 3; medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get() - 3;
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) { } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) &&
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 3; medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 3;
} }
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) { if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get() }); medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get() });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) { } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 3) }); medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 3) });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) { } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) &&
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 3) }); medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 3) });
} }
return medallions; return medallions;
@ -275,45 +275,55 @@ uint8_t TokensRequiredBySettings() {
} }
std::vector<std::pair<RandomizerCheck, std::function<bool()>>> conditionalAlwaysHints = { std::vector<std::pair<RandomizerCheck, std::function<bool()>>> conditionalAlwaysHints = {
std::make_pair(RC_MARKET_10_BIG_POES, []() { std::make_pair(RC_MARKET_10_BIG_POES,
[]() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return ctx->GetOption(RSK_BIG_POE_COUNT).Get() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT); return ctx->GetOption(RSK_BIG_POE_COUNT).Get() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
}), // Remember, the option's value being 3 means 4 are required }), // Remember, the option's value being 3 means 4 are required
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() { std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH,
[]() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return !ctx->GetOption(RSK_MASK_SHOP_HINT) && !ctx->GetOption(RSK_COMPLETE_MASK_QUEST); return !ctx->GetOption(RSK_MASK_SHOP_HINT) && !ctx->GetOption(RSK_COMPLETE_MASK_QUEST);
}), }),
std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME, []() { std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME,
[]() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return StonesRequiredBySettings() < 2 && !ctx->GetOption(RSK_OOT_HINT); return StonesRequiredBySettings() < 2 && !ctx->GetOption(RSK_OOT_HINT);
}), }),
std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }), std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }),
std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }), std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }),
std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, []() { std::make_pair(RC_DMT_TRADE_CLAIM_CHECK,
[]() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return !ctx->GetOption(RSK_BIGGORON_HINT); return !ctx->GetOption(RSK_BIGGORON_HINT);
}), }),
std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD, []() { std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD,
[]() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return !ctx->GetOption(RSK_KAK_30_SKULLS_HINT) && TokensRequiredBySettings() < 30; return !ctx->GetOption(RSK_KAK_30_SKULLS_HINT) && TokensRequiredBySettings() < 30;
}), }),
std::make_pair(RC_KAK_40_GOLD_SKULLTULA_REWARD, []() { std::make_pair(RC_KAK_40_GOLD_SKULLTULA_REWARD,
[]() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return !ctx->GetOption(RSK_KAK_40_SKULLS_HINT) && TokensRequiredBySettings() < 40; return !ctx->GetOption(RSK_KAK_40_SKULLS_HINT) && TokensRequiredBySettings() < 40;
}), }),
std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD, []() { std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD,
[]() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return !ctx->GetOption(RSK_KAK_50_SKULLS_HINT) && TokensRequiredBySettings() < 50; return !ctx->GetOption(RSK_KAK_50_SKULLS_HINT) && TokensRequiredBySettings() < 50;
}), }),
std::make_pair(RC_ZR_FROGS_OCARINA_GAME, []() { std::make_pair(RC_ZR_FROGS_OCARINA_GAME,
[]() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return !ctx->GetOption(RSK_FROGS_HINT); return !ctx->GetOption(RSK_FROGS_HINT);
}), }),
std::make_pair(RC_KF_LINKS_HOUSE_COW, []() { std::make_pair(RC_KF_LINKS_HOUSE_COW,
[]() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return !ctx->GetOption(RSK_MALON_HINT); return !ctx->GetOption(RSK_MALON_HINT);
}), }),
std::make_pair(RC_KAK_100_GOLD_SKULLTULA_REWARD, []() { std::make_pair(RC_KAK_100_GOLD_SKULLTULA_REWARD,
[]() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return !ctx->GetOption(RSK_KAK_100_SKULLS_HINT) && TokensRequiredBySettings() < 100; return !ctx->GetOption(RSK_KAK_100_SKULLS_HINT) && TokensRequiredBySettings() < 100;
}), }),
@ -339,7 +349,8 @@ static std::vector<RandomizerCheck> GetAccessibleGossipStones(const RandomizerCh
return accessibleGossipStones; return accessibleGossipStones;
} }
bool IsReachableWithout(std::vector<RandomizerCheck> locsToCheck, RandomizerCheck excludedCheck, bool resetAfter = true){ bool IsReachableWithout(std::vector<RandomizerCheck> locsToCheck, RandomizerCheck excludedCheck,
bool resetAfter = true) {
// temporarily remove the hinted location's item, and then perform a // temporarily remove the hinted location's item, and then perform a
// reachability search for this check RANDOTODO convert excludedCheck to an ItemLocation // reachability search for this check RANDOTODO convert excludedCheck to an ItemLocation
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
@ -368,21 +379,19 @@ static void SetAllInAreaAsHintAccesible(RandomizerArea area, std::vector<Randomi
} }
} }
static void AddGossipStoneHint( const RandomizerCheck gossipStone, static void AddGossipStoneHint(const RandomizerCheck gossipStone, const HintType hintType,
const HintType hintType, const std::string distributionName, const std::vector<RandomizerHintTextKey> hintKeys,
const std::string distributionName, const std::vector<RandomizerCheck> locations, const std::vector<RandomizerArea> areas,
const std::vector<RandomizerHintTextKey> hintKeys,
const std::vector<RandomizerCheck> locations,
const std::vector<RandomizerArea> areas,
const std::vector<TrialKey> trials) { const std::vector<TrialKey> trials) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
ctx->AddHint(StaticData::gossipStoneCheckToHint[gossipStone], Hint(StaticData::gossipStoneCheckToHint[gossipStone], hintType, distributionName, hintKeys, locations, areas, trials)); ctx->AddHint(StaticData::gossipStoneCheckToHint[gossipStone],
ctx->GetItemLocation(gossipStone)->SetPlacedItem(RG_HINT); //RANDOTODO, better gossip stone to location to hint key system Hint(StaticData::gossipStoneCheckToHint[gossipStone], hintType, distributionName, hintKeys, locations,
areas, trials));
ctx->GetItemLocation(gossipStone)
->SetPlacedItem(RG_HINT); // RANDOTODO, better gossip stone to location to hint key system
} }
static void AddGossipStoneHintCopies(uint8_t copies, static void AddGossipStoneHintCopies(uint8_t copies, const HintType hintType, const std::string distributionName,
const HintType hintType,
const std::string distributionName,
const std::vector<RandomizerHintTextKey> hintKeys = {}, const std::vector<RandomizerHintTextKey> hintKeys = {},
const std::vector<RandomizerCheck> locations = {}, const std::vector<RandomizerCheck> locations = {},
const std::vector<RandomizerArea> areas = {}, const std::vector<RandomizerArea> areas = {},
@ -427,11 +436,8 @@ static bool CreateHint(RandomizerCheck location, uint8_t copies, HintType type,
return true; return true;
} }
static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHintLocations, uint8_t copies,
static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHintLocations, HintType type, std::string distributionName) {
uint8_t copies,
HintType type,
std::string distributionName) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
// return if there aren't any hintable locations or gossip stones available // return if there aren't any hintable locations or gossip stones available
@ -447,7 +453,8 @@ static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHi
SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n"); SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n");
return RC_UNKNOWN_CHECK; return RC_UNKNOWN_CHECK;
} }
hintedLocation = RandomElement(possibleHintLocations, true); //removing the location to avoid it being hinted again on fail hintedLocation =
RandomElement(possibleHintLocations, true); // removing the location to avoid it being hinted again on fail
SPDLOG_DEBUG("\tLocation: "); SPDLOG_DEBUG("\tLocation: ");
SPDLOG_DEBUG(Rando::StaticData::GetLocation(hintedLocation)->GetName()); SPDLOG_DEBUG(Rando::StaticData::GetLocation(hintedLocation)->GetName());
@ -466,8 +473,8 @@ static std::vector<RandomizerCheck> FilterHintability(std::vector<RandomizerChec
std::function<bool(RandomizerCheck)> extraFilter = NoFilter) { std::function<bool(RandomizerCheck)> extraFilter = NoFilter) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return FilterFromPool(locations, [extraFilter, ctx](const RandomizerCheck loc) { return FilterFromPool(locations, [extraFilter, ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsAHintAccessible()) return ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsAHintAccessible()) &&
&& extraFilter(loc); extraFilter(loc);
}); });
} }
@ -486,7 +493,8 @@ static void CreateTrialHints(uint8_t copies) {
} else if (ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) { // zero trials } else if (ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) { // zero trials
AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", { RHT_ZERO_TRIALS }); AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", { RHT_ZERO_TRIALS });
} else { } else {
std::vector<TrialInfo*> trials = ctx->GetTrials()->GetTrialList(); //there's probably a way to remove this assignment std::vector<TrialInfo*> trials =
ctx->GetTrials()->GetTrialList(); // there's probably a way to remove this assignment
if (ctx->GetOption(RSK_TRIAL_COUNT).Get() >= 4) { // 4 or 5 required trials, get skipped trials if (ctx->GetOption(RSK_TRIAL_COUNT).Get() >= 4) { // 4 or 5 required trials, get skipped trials
trials = FilterFromPool(trials, [](TrialInfo* trial) { return trial->IsSkipped(); }); trials = FilterFromPool(trials, [](TrialInfo* trial) { return trial->IsSkipped(); });
} else { // 1 to 3 trials, get requried trials } else { // 1 to 3 trials, get requried trials
@ -508,22 +516,28 @@ void CreateWarpSongTexts() {
RandomizerArea destination = entrance->GetConnectedRegion()->GetFirstArea(); RandomizerArea destination = entrance->GetConnectedRegion()->GetFirstArea();
switch (entrance->GetIndex()) { switch (entrance->GetIndex()) {
case 0x0600: // minuet RANDOTODO make into entrance hints when they are added case 0x0600: // minuet RANDOTODO make into entrance hints when they are added
ctx->AddHint(RH_MINUET_WARP_LOC, Hint(RH_MINUET_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); ctx->AddHint(RH_MINUET_WARP_LOC,
Hint(RH_MINUET_WARP_LOC, HINT_TYPE_AREA, "", { RHT_WARP_SONG }, {}, { destination }));
break; break;
case 0x04F6: // bolero case 0x04F6: // bolero
ctx->AddHint(RH_BOLERO_WARP_LOC, Hint(RH_BOLERO_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); ctx->AddHint(RH_BOLERO_WARP_LOC,
Hint(RH_BOLERO_WARP_LOC, HINT_TYPE_AREA, "", { RHT_WARP_SONG }, {}, { destination }));
break; break;
case 0x0604: // serenade case 0x0604: // serenade
ctx->AddHint(RH_SERENADE_WARP_LOC, Hint(RH_SERENADE_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); ctx->AddHint(RH_SERENADE_WARP_LOC, Hint(RH_SERENADE_WARP_LOC, HINT_TYPE_AREA, "", { RHT_WARP_SONG },
{}, { destination }));
break; break;
case 0x01F1: // requiem case 0x01F1: // requiem
ctx->AddHint(RH_REQUIEM_WARP_LOC, Hint(RH_REQUIEM_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); ctx->AddHint(RH_REQUIEM_WARP_LOC,
Hint(RH_REQUIEM_WARP_LOC, HINT_TYPE_AREA, "", { RHT_WARP_SONG }, {}, { destination }));
break; break;
case 0x0568: // nocturne case 0x0568: // nocturne
ctx->AddHint(RH_NOCTURNE_WARP_LOC, Hint(RH_NOCTURNE_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); ctx->AddHint(RH_NOCTURNE_WARP_LOC, Hint(RH_NOCTURNE_WARP_LOC, HINT_TYPE_AREA, "", { RHT_WARP_SONG },
{}, { destination }));
break; break;
case 0x05F4: // prelude case 0x05F4: // prelude
ctx->AddHint(RH_PRELUDE_WARP_LOC, Hint(RH_PRELUDE_WARP_LOC, HINT_TYPE_AREA, "", {RHT_WARP_SONG}, {}, {destination})); ctx->AddHint(RH_PRELUDE_WARP_LOC,
Hint(RH_PRELUDE_WARP_LOC, HINT_TYPE_AREA, "", { RHT_WARP_SONG }, {}, { destination }));
break; break;
default: default:
break; break;
@ -539,35 +553,49 @@ int32_t getRandomWeight(int32_t totalWeight){
return Random(1, totalWeight); return Random(1, totalWeight);
} }
static void DistributeHints(std::vector<uint8_t>& selected, size_t stoneCount, std::vector<HintDistributionSetting> distTable, uint8_t junkWieght, bool addFixed = true){ static void DistributeHints(std::vector<uint8_t>& selected, size_t stoneCount,
std::vector<HintDistributionSetting> distTable, uint8_t junkWieght, bool addFixed = true) {
int32_t totalWeight = junkWieght; // Start with our Junk Weight, the natural chance of a junk hint int32_t totalWeight = junkWieght; // Start with our Junk Weight, the natural chance of a junk hint
for (size_t c=0; c < distTable.size(); c++){ //Gather the weights of each distribution and, if it's the first pass, apply fixed hints for (size_t c = 0; c < distTable.size();
totalWeight += distTable[c].weight; //Note that PlaceHints will set weights of distributions to zero if it can't place anything from them c++) { // Gather the weights of each distribution and, if it's the first pass, apply fixed hints
totalWeight += distTable[c].weight; // Note that PlaceHints will set weights of distributions to zero if it
// can't place anything from them
if (addFixed) { if (addFixed) {
selected[c] += distTable[c].fixed; selected[c] += distTable[c].fixed;
stoneCount -= distTable[c].fixed * distTable[c].copies; stoneCount -= distTable[c].fixed * distTable[c].copies;
} }
} }
int32_t currentWeight = getRandomWeight(totalWeight); //Initialise with the first random weight from 1 to the total. int32_t currentWeight = getRandomWeight(totalWeight); // Initialise with the first random weight from 1 to the
while(stoneCount > 0 && totalWeight > 0){//Loop until we run out of stones or have no TotalWeight. 0 totalWeight means junkWeight is 0 // total.
while (stoneCount > 0 &&
totalWeight >
0) { // Loop until we run out of stones or have no TotalWeight. 0 totalWeight means junkWeight is 0
// and that all weights have been 0'd out for another reason, and skips to placing all junk hints // and that all weights have been 0'd out for another reason, and skips to placing all junk hints
for (size_t distribution = 0; distribution < distTable.size(); distribution++) { for (size_t distribution = 0; distribution < distTable.size(); distribution++) {
currentWeight -= distTable[distribution].weight; //go over each distribution, subtracting the weight each time. Once we reach zero or less, currentWeight -=
distTable[distribution]
.weight; // go over each distribution, subtracting the weight each time. Once we reach zero or less,
if (currentWeight <= 0) { // tell the system to make 1 of that hint, unless not enough stones remain if (currentWeight <= 0) { // tell the system to make 1 of that hint, unless not enough stones remain
if (stoneCount >= distTable[distribution].copies && distTable[distribution].copies > 0) { if (stoneCount >= distTable[distribution].copies && distTable[distribution].copies > 0) {
selected[distribution] += 1; //if we have enough stones, and copies are not zero, assign 1 to this hint type, remove the stones, and break selected[distribution] += 1; // if we have enough stones, and copies are not zero, assign 1 to this
// hint type, remove the stones, and break
stoneCount -= distTable[distribution].copies; stoneCount -= distTable[distribution].copies;
break; // This leaves the whole for loop break; // This leaves the whole for loop
} else { //If we don't have the stones, or copies is 0 despite there being the wieght to trigger a hit, temporerally set wieght to zero } else { // If we don't have the stones, or copies is 0 despite there being the wieght to trigger a hit,
totalWeight -= distTable[distribution].weight; //Unlike PlaceHint, distTable is passed by value here, making this temporary // temporerally set wieght to zero
distTable[distribution].weight = 0; //this is so we can still roll this hint type if more stones free up later totalWeight -=
distTable[distribution]
.weight; // Unlike PlaceHint, distTable is passed by value here, making this temporary
distTable[distribution].weight =
0; // this is so we can still roll this hint type if more stones free up later
break; break;
} }
} }
} }
// if there's still weight then it's junk, as the leftover weight is junkWeight // if there's still weight then it's junk, as the leftover weight is junkWeight
if (currentWeight > 0){ //zero TotalWeight breaks the while loop and hits the fallback, so skipping this is fine in that case if (currentWeight >
0) { // zero TotalWeight breaks the while loop and hits the fallback, so skipping this is fine in that case
selected[selected.size() - 1] += 1; selected[selected.size() - 1] += 1;
stoneCount -= 1; stoneCount -= 1;
} }
@ -586,14 +614,17 @@ uint8_t PlaceHints(std::vector<uint8_t>& selectedHints, std::vector<HintDistribu
std::vector<RandomizerCheck> hintTypePool = FilterHintability(ctx->allLocations, distribution.filter); std::vector<RandomizerCheck> hintTypePool = FilterHintability(ctx->allLocations, distribution.filter);
for (uint8_t numHint = 0; numHint < selectedHints[curSlot]; numHint++) { for (uint8_t numHint = 0; numHint < selectedHints[curSlot]; numHint++) {
hintTypePool = FilterHintability(hintTypePool); hintTypePool = FilterHintability(hintTypePool);
SPDLOG_DEBUG("Attempting to make hint of type: " + StaticData::hintTypeNames[distribution.type].GetEnglish(MF_CLEAN) + "\n"); SPDLOG_DEBUG("Attempting to make hint of type: " +
StaticData::hintTypeNames[distribution.type].GetEnglish(MF_CLEAN) + "\n");
RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK; RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK;
hintedLocation = CreateRandomHint(hintTypePool, distribution.copies, distribution.type, distribution.name); hintedLocation = CreateRandomHint(hintTypePool, distribution.copies, distribution.type, distribution.name);
if (hintedLocation == RC_UNKNOWN_CHECK){ //if hint failed to place, remove all wieght and copies then return the number of stones to redistribute if (hintedLocation == RC_UNKNOWN_CHECK) { // if hint failed to place, remove all wieght and copies then
// return the number of stones to redistribute
uint8_t hintsToRemove = (selectedHints[curSlot] - numHint) * distribution.copies; uint8_t hintsToRemove = (selectedHints[curSlot] - numHint) * distribution.copies;
selectedHints[curSlot] = 0; //as distTable is passed by refernce here, these changes stick for the rest of this seed generation selectedHints[curSlot] = 0; // as distTable is passed by refernce here, these changes stick for the rest
// of this seed generation
distTable[curSlot].copies = 0; // and prevent future distribution from choosing this slot distTable[curSlot].copies = 0; // and prevent future distribution from choosing this slot
distTable[curSlot].weight = 0; distTable[curSlot].weight = 0;
return hintsToRemove; return hintsToRemove;
@ -630,8 +661,7 @@ void CreateStoneHints() {
// If we have Rainbow Bridge set to Greg and the greg hint isn't useful, add a hint for where Greg is // If we have Rainbow Bridge set to Greg and the greg hint isn't useful, add a hint for where Greg is
// Do we really need this with the greg hint? // Do we really need this with the greg hint?
auto gregLocations = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) { auto gregLocations = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return ( return ((ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) &&
(ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) &&
ctx->GetItemLocation(loc)->IsHintable() && ctx->GetItemLocation(loc)->IsHintable() &&
!(ctx->GetOption(RSK_GREG_HINT) && (IsReachableWithout({ RC_GREG_HINT }, loc, true))); !(ctx->GetOption(RSK_GREG_HINT) && (IsReachableWithout({ RC_GREG_HINT }, loc, true)));
}); });
@ -678,16 +708,20 @@ void CreateStoneHints() {
ReachabilitySearch({}); ReachabilitySearch({});
} }
std::vector<RandomizerCheck> FindItemsAndMarkHinted(std::vector<RandomizerGet> items, std::vector<RandomizerCheck> hintChecks){ std::vector<RandomizerCheck> FindItemsAndMarkHinted(std::vector<RandomizerGet> items,
std::vector<RandomizerCheck> hintChecks) {
std::vector<RandomizerCheck> locations = {}; std::vector<RandomizerCheck> locations = {};
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
for (size_t c = 0; c < items.size(); c++) { for (size_t c = 0; c < items.size(); c++) {
std::vector<RandomizerCheck> found = FilterFromPool(ctx->allLocations, [items, ctx, c](const RandomizerCheck loc) { std::vector<RandomizerCheck> found =
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == items[c];}); FilterFromPool(ctx->allLocations, [items, ctx, c](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == items[c];
});
if (found.size() > 0) { if (found.size() > 0) {
locations.push_back(found[0]); locations.push_back(found[0]);
// RANDOTODO make the called functions of this always return true if empty hintChecks are provided // RANDOTODO make the called functions of this always return true if empty hintChecks are provided
if (!ctx->GetItemLocation(found[0])->IsAHintAccessible() && (hintChecks.size() == 0 || IsReachableWithout(hintChecks, found[0],true))){ if (!ctx->GetItemLocation(found[0])->IsAHintAccessible() &&
(hintChecks.size() == 0 || IsReachableWithout(hintChecks, found[0], true))) {
ctx->GetItemLocation(found[0])->SetHintAccesible(); ctx->GetItemLocation(found[0])->SetHintAccesible();
} }
} else { } else {
@ -702,10 +736,12 @@ void CreateChildAltarHint() {
if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled() && ctx->GetOption(RSK_TOT_ALTAR_HINT)) { if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled() && ctx->GetOption(RSK_TOT_ALTAR_HINT)) {
std::vector<RandomizerCheck> stoneLocs = {}; std::vector<RandomizerCheck> stoneLocs = {};
// 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) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { 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)) {
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 = FindItemsAndMarkHinted({RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE}, {RC_ALTAR_HINT_CHILD}); stoneLocs =
FindItemsAndMarkHinted({ RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE }, { RC_ALTAR_HINT_CHILD });
} }
std::vector<RandomizerArea> stoneAreas = {}; std::vector<RandomizerArea> stoneAreas = {};
for (auto loc : stoneLocs) { for (auto loc : stoneLocs) {
@ -723,11 +759,14 @@ void CreateAdultAltarHint() {
std::vector<RandomizerCheck> medallionLocs = {}; std::vector<RandomizerCheck> medallionLocs = {};
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) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) ||
medallionLocs = FindItemsAndMarkHinted({RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION}, ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) {
medallionLocs = FindItemsAndMarkHinted({ RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION,
RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION },
{}); {});
} else { } else {
medallionLocs = FindItemsAndMarkHinted({RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION}, medallionLocs = FindItemsAndMarkHinted({ RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION,
RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION },
{ RC_ALTAR_HINT_ADULT }); { RC_ALTAR_HINT_ADULT });
} }
} }
@ -746,7 +785,8 @@ void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){
if (!ctx->GetHint(hint)->IsEnabled()) { if (!ctx->GetHint(hint)->IsEnabled()) {
OptionValue& option = ctx->GetOption(staticData.setting); OptionValue& option = ctx->GetOption(staticData.setting);
if ((std::holds_alternative<bool>(staticData.condition) && option.Is(std::get<bool>(staticData.condition))) || if ((std::holds_alternative<bool>(staticData.condition) && option.Is(std::get<bool>(staticData.condition))) ||
(std::holds_alternative<uint8_t>(staticData.condition) && option.Is(std::get<uint8_t>(staticData.condition)))){ (std::holds_alternative<uint8_t>(staticData.condition) &&
option.Is(std::get<uint8_t>(staticData.condition)))) {
std::vector<RandomizerCheck> locations = {}; std::vector<RandomizerCheck> locations = {};
if (staticData.targetItems.size() > 0) { if (staticData.targetItems.size() > 0) {
@ -760,7 +800,8 @@ void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){
for (auto loc : locations) { for (auto loc : locations) {
ctx->GetItemLocation(loc)->SetHintAccesible(); ctx->GetItemLocation(loc)->SetHintAccesible();
if (ctx->GetItemLocation(loc)->GetAreas().empty()) { if (ctx->GetItemLocation(loc)->GetAreas().empty()) {
//If we get to here then it means a location got through with no area assignment, which means something went wrong elsewhere. // If we get to here then it means a location got through with no area assignment, which means
// something went wrong elsewhere.
SPDLOG_DEBUG("Attempted to hint location with no areas: "); SPDLOG_DEBUG("Attempted to hint location with no areas: ");
SPDLOG_DEBUG(Rando::StaticData::GetLocation(loc)->GetName()); SPDLOG_DEBUG(Rando::StaticData::GetLocation(loc)->GetName());
// assert(false); // assert(false);
@ -770,13 +811,15 @@ void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){
} }
} }
// hintKeys are defaulted to in the hint object and do not need to be specified // hintKeys are defaulted to in the hint object and do not need to be specified
ctx->AddHint(hint, Hint(hint, staticData.type, {}, locations, areas, {}, staticData.yourPocket, staticData.num)); ctx->AddHint(hint,
Hint(hint, staticData.type, {}, locations, areas, {}, staticData.yourPocket, staticData.num));
} }
} }
} }
void CreateStaticItemHint(RandomizerHint hintKey, std::vector<RandomizerHintTextKey> hintTextKeys, void CreateStaticItemHint(RandomizerHint hintKey, std::vector<RandomizerHintTextKey> hintTextKeys,
std::vector<RandomizerGet> items, std::vector<RandomizerCheck> hintChecks, bool yourPocket = false) { std::vector<RandomizerGet> items, std::vector<RandomizerCheck> hintChecks,
bool yourPocket = false) {
// RANDOTODO choose area in case there are multiple // RANDOTODO choose area in case there are multiple
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
std::vector<RandomizerCheck> locations = FindItemsAndMarkHinted(items, hintChecks); std::vector<RandomizerCheck> locations = FindItemsAndMarkHinted(items, hintChecks);
@ -798,10 +841,13 @@ void CreateGanondorfHint(){
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_GANONDORF_HINT) && !ctx->GetHint(RH_GANONDORF_HINT)->IsEnabled()) { if (ctx->GetOption(RSK_GANONDORF_HINT) && !ctx->GetHint(RH_GANONDORF_HINT)->IsEnabled()) {
if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) { if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) {
CreateStaticItemHint(RH_GANONDORF_HINT, {RHT_GANONDORF_HINT_LA_ONLY, RHT_GANONDORF_HINT_MS_ONLY, RHT_GANONDORF_HINT_LA_AND_MS}, CreateStaticItemHint(
RH_GANONDORF_HINT,
{ RHT_GANONDORF_HINT_LA_ONLY, RHT_GANONDORF_HINT_MS_ONLY, RHT_GANONDORF_HINT_LA_AND_MS },
{ RG_LIGHT_ARROWS, RG_MASTER_SWORD }, { RC_GANONDORF_HINT }, true); { RG_LIGHT_ARROWS, RG_MASTER_SWORD }, { RC_GANONDORF_HINT }, true);
} else { } else {
CreateStaticItemHint(RH_GANONDORF_HINT, {RHT_GANONDORF_HINT_LA_ONLY}, {RG_LIGHT_ARROWS}, {RC_GANONDORF_HINT}, true); CreateStaticItemHint(RH_GANONDORF_HINT, { RHT_GANONDORF_HINT_LA_ONLY }, { RG_LIGHT_ARROWS },
{ RC_GANONDORF_HINT }, true);
} }
} }
} }

View file

@ -13,33 +13,13 @@
std::vector<RandomizerGet> ItemPool = {}; std::vector<RandomizerGet> ItemPool = {};
std::vector<RandomizerGet> PendingJunkPool = {}; std::vector<RandomizerGet> PendingJunkPool = {};
const std::array<RandomizerGet, 9> dungeonRewards = { const std::array<RandomizerGet, 9> dungeonRewards = {
RG_KOKIRI_EMERALD, RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION,
RG_GORON_RUBY, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION, RG_LIGHT_MEDALLION,
RG_ZORA_SAPPHIRE,
RG_FOREST_MEDALLION,
RG_FIRE_MEDALLION,
RG_WATER_MEDALLION,
RG_SPIRIT_MEDALLION,
RG_SHADOW_MEDALLION,
RG_LIGHT_MEDALLION,
}; };
const std::array<RandomizerGet, 16> JunkPoolItems = { const std::array<RandomizerGet, 16> JunkPoolItems = {
RG_BOMBS_5, RG_BOMBS_5, RG_BOMBS_10, RG_BOMBS_20, RG_DEKU_NUTS_5, RG_DEKU_STICK_1, RG_DEKU_SEEDS_30,
RG_BOMBS_10, RG_RECOVERY_HEART, RG_ARROWS_5, RG_ARROWS_10, RG_ARROWS_30, RG_BLUE_RUPEE, RG_RED_RUPEE,
RG_BOMBS_20, RG_PURPLE_RUPEE, RG_HUGE_RUPEE, RG_DEKU_NUTS_10, RG_ICE_TRAP,
RG_DEKU_NUTS_5,
RG_DEKU_STICK_1,
RG_DEKU_SEEDS_30,
RG_RECOVERY_HEART,
RG_ARROWS_5,
RG_ARROWS_10,
RG_ARROWS_30,
RG_BLUE_RUPEE,
RG_RED_RUPEE,
RG_PURPLE_RUPEE,
RG_HUGE_RUPEE,
RG_DEKU_NUTS_10,
RG_ICE_TRAP,
}; };
const std::array<RandomizerGet, 59> alwaysItems = { const std::array<RandomizerGet, 59> alwaysItems = {
RG_BIGGORON_SWORD, RG_BIGGORON_SWORD,
@ -212,13 +192,7 @@ const std::array<RandomizerGet, 2> DC_MQ = {
RG_BLUE_RUPEE, RG_BLUE_RUPEE,
}; };
const std::array<RandomizerGet, 7> JB_MQ = { const std::array<RandomizerGet, 7> JB_MQ = {
RG_DEKU_NUTS_5, RG_DEKU_NUTS_5, RG_DEKU_NUTS_5, RG_DEKU_NUTS_5, RG_DEKU_NUTS_5, RG_RECOVERY_HEART, RG_DEKU_SHIELD, RG_DEKU_STICK_1,
RG_DEKU_NUTS_5,
RG_DEKU_NUTS_5,
RG_DEKU_NUTS_5,
RG_RECOVERY_HEART,
RG_DEKU_SHIELD,
RG_DEKU_STICK_1,
}; };
const std::array<RandomizerGet, 3> FoT_Vanilla = { const std::array<RandomizerGet, 3> FoT_Vanilla = {
RG_RECOVERY_HEART, RG_RECOVERY_HEART,
@ -255,13 +229,7 @@ const std::array<RandomizerGet, 3> ShT_MQ = {
RG_RED_RUPEE, RG_RED_RUPEE,
}; };
const std::array<RandomizerGet, 7> BW_Vanilla = { const std::array<RandomizerGet, 7> BW_Vanilla = {
RG_RECOVERY_HEART, RG_RECOVERY_HEART, RG_BOMBS_10, RG_HUGE_RUPEE, RG_DEKU_NUTS_5, RG_DEKU_NUTS_10, RG_DEKU_SHIELD, RG_HYLIAN_SHIELD,
RG_BOMBS_10,
RG_HUGE_RUPEE,
RG_DEKU_NUTS_5,
RG_DEKU_NUTS_10,
RG_DEKU_SHIELD,
RG_HYLIAN_SHIELD,
}; };
const std::array<RandomizerGet, 4> GTG_Vanilla = { const std::array<RandomizerGet, 4> GTG_Vanilla = {
RG_ARROWS_30, RG_ARROWS_30,
@ -270,11 +238,7 @@ const std::array<RandomizerGet, 4> GTG_Vanilla = {
RG_HUGE_RUPEE, RG_HUGE_RUPEE,
}; };
const std::array<RandomizerGet, 5> GTG_MQ = { const std::array<RandomizerGet, 5> GTG_MQ = {
RG_LOSER_GREEN_RUPEE, RG_LOSER_GREEN_RUPEE, RG_LOSER_GREEN_RUPEE, RG_ARROWS_10, RG_GREEN_RUPEE, RG_PURPLE_RUPEE,
RG_LOSER_GREEN_RUPEE,
RG_ARROWS_10,
RG_GREEN_RUPEE,
RG_PURPLE_RUPEE,
}; };
const std::array<RandomizerGet, 4> GC_Vanilla = { const std::array<RandomizerGet, 4> GC_Vanilla = {
RG_BLUE_RUPEE, RG_BLUE_RUPEE,
@ -283,11 +247,7 @@ const std::array<RandomizerGet, 4> GC_Vanilla = {
RG_ARROWS_30, RG_ARROWS_30,
}; };
const std::array<RandomizerGet, 5> GC_MQ = { const std::array<RandomizerGet, 5> GC_MQ = {
RG_ARROWS_10, RG_ARROWS_10, RG_ARROWS_10, RG_BOMBS_5, RG_RED_RUPEE, RG_RECOVERY_HEART,
RG_ARROWS_10,
RG_BOMBS_5,
RG_RED_RUPEE,
RG_RECOVERY_HEART,
}; };
const std::array<RandomizerGet, 11> normalBottles = { const std::array<RandomizerGet, 11> normalBottles = {
RG_EMPTY_BOTTLE, RG_EMPTY_BOTTLE,
@ -303,99 +263,29 @@ const std::array<RandomizerGet, 11> normalBottles = {
RG_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE,
}; };
const std::array<RandomizerGet, 28> normalRupees = { const std::array<RandomizerGet, 28> normalRupees = {
RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE,
RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE,
RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE,
RG_BLUE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE,
RG_BLUE_RUPEE, RG_PURPLE_RUPEE, RG_HUGE_RUPEE, RG_HUGE_RUPEE, RG_HUGE_RUPEE,
RG_BLUE_RUPEE,
RG_BLUE_RUPEE,
RG_BLUE_RUPEE,
RG_BLUE_RUPEE,
RG_BLUE_RUPEE,
RG_BLUE_RUPEE,
RG_BLUE_RUPEE,
RG_BLUE_RUPEE,
RG_RED_RUPEE,
RG_RED_RUPEE,
RG_RED_RUPEE,
RG_RED_RUPEE,
RG_RED_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_HUGE_RUPEE,
RG_HUGE_RUPEE,
RG_HUGE_RUPEE,
}; };
const std::array<RandomizerGet, 28> shopsanityRupees = { const std::array<RandomizerGet, 28> shopsanityRupees = {
RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE,
RG_BLUE_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE, RG_RED_RUPEE,
RG_RED_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE,
RG_RED_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_PURPLE_RUPEE, RG_HUGE_RUPEE, RG_HUGE_RUPEE,
RG_RED_RUPEE, RG_HUGE_RUPEE, RG_HUGE_RUPEE, RG_HUGE_RUPEE, RG_HUGE_RUPEE,
RG_RED_RUPEE,
RG_RED_RUPEE,
RG_RED_RUPEE,
RG_RED_RUPEE,
RG_RED_RUPEE,
RG_RED_RUPEE,
RG_RED_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_PURPLE_RUPEE,
RG_HUGE_RUPEE,
RG_HUGE_RUPEE,
RG_HUGE_RUPEE,
RG_HUGE_RUPEE,
RG_HUGE_RUPEE,
RG_HUGE_RUPEE,
}; };
const std::array<RandomizerGet, 19> dekuScrubItems = { const std::array<RandomizerGet, 19> dekuScrubItems = {
RG_DEKU_NUTS_5, RG_DEKU_NUTS_5, RG_DEKU_NUTS_5, RG_DEKU_NUTS_5, RG_DEKU_NUTS_5, RG_DEKU_NUTS_5,
RG_DEKU_NUTS_5, RG_DEKU_STICK_1, RG_BOMBS_5, RG_BOMBS_5, RG_BOMBS_5, RG_BOMBS_5,
RG_DEKU_NUTS_5, RG_BOMBS_5, RG_RECOVERY_HEART, RG_RECOVERY_HEART, RG_RECOVERY_HEART, RG_RECOVERY_HEART,
RG_DEKU_NUTS_5, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE, RG_BLUE_RUPEE,
RG_DEKU_NUTS_5,
RG_DEKU_STICK_1,
RG_BOMBS_5,
RG_BOMBS_5,
RG_BOMBS_5,
RG_BOMBS_5,
RG_BOMBS_5,
RG_RECOVERY_HEART,
RG_RECOVERY_HEART,
RG_RECOVERY_HEART,
RG_RECOVERY_HEART,
RG_BLUE_RUPEE,
RG_BLUE_RUPEE,
RG_BLUE_RUPEE,
RG_BLUE_RUPEE,
}; };
const std::array<RandomizerGet, 12> songList = { const std::array<RandomizerGet, 12> songList = {
RG_ZELDAS_LULLABY, RG_ZELDAS_LULLABY, RG_EPONAS_SONG, RG_SUNS_SONG, RG_SARIAS_SONG,
RG_EPONAS_SONG, RG_SONG_OF_TIME, RG_SONG_OF_STORMS, RG_MINUET_OF_FOREST, RG_PRELUDE_OF_LIGHT,
RG_SUNS_SONG, RG_BOLERO_OF_FIRE, RG_SERENADE_OF_WATER, RG_NOCTURNE_OF_SHADOW, RG_REQUIEM_OF_SPIRIT,
RG_SARIAS_SONG,
RG_SONG_OF_TIME,
RG_SONG_OF_STORMS,
RG_MINUET_OF_FOREST,
RG_PRELUDE_OF_LIGHT,
RG_BOLERO_OF_FIRE,
RG_SERENADE_OF_WATER,
RG_NOCTURNE_OF_SHADOW,
RG_REQUIEM_OF_SPIRIT,
}; };
const std::array<RandomizerGet, 10> tradeItems = { const std::array<RandomizerGet, 10> tradeItems = {
RG_POCKET_EGG, RG_POCKET_EGG,
@ -414,8 +304,7 @@ void AddItemToPool(std::vector<RandomizerGet>& pool, RandomizerGet item, size_t
pool.insert(pool.end(), count, item); pool.insert(pool.end(), count, item);
} }
template <typename FromPool> template <typename FromPool> static void AddItemsToPool(std::vector<RandomizerGet>& toPool, const FromPool& fromPool) {
static void AddItemsToPool(std::vector<RandomizerGet>& toPool, const FromPool& fromPool) {
AddElementsToPool(toPool, fromPool); AddElementsToPool(toPool, fromPool);
} }
@ -429,7 +318,8 @@ static void AddRandomBottle(std::vector<RandomizerGet>& bottlePool) {
RandomizerGet GetJunkItem() { RandomizerGet GetJunkItem() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_MAYHEM) || ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_ONSLAUGHT)) { if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_MAYHEM) ||
ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_ONSLAUGHT)) {
return RG_ICE_TRAP; return RG_ICE_TRAP;
} else if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_EXTRA)) { } else if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_EXTRA)) {
return RandomElement(JunkPoolItems); return RandomElement(JunkPoolItems);
@ -853,7 +743,8 @@ void GenerateItemPool() {
} }
if (ctx->GetOption(RSK_SHUFFLE_100_GS_REWARD)) { if (ctx->GetOption(RSK_SHUFFLE_100_GS_REWARD)) {
if (ctx->GetOption(RSK_SHUFFLE_TOKENS).IsNot(RO_TOKENSANITY_OFF) && ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { if (ctx->GetOption(RSK_SHUFFLE_TOKENS).IsNot(RO_TOKENSANITY_OFF) &&
ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
AddItemToPool(PendingJunkPool, RG_GOLD_SKULLTULA_TOKEN, 10); AddItemToPool(PendingJunkPool, RG_GOLD_SKULLTULA_TOKEN, 10);
} }
AddItemToMainPool(RG_HUGE_RUPEE); AddItemToMainPool(RG_HUGE_RUPEE);
@ -943,7 +834,8 @@ void GenerateItemPool() {
} }
} }
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
if (ctx->GetOption(RSK_KEYRINGS_GERUDO_FORTRESS) && ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) && ctx->GetOption(RSK_KEYRINGS) ) { if (ctx->GetOption(RSK_KEYRINGS_GERUDO_FORTRESS) &&
ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) && ctx->GetOption(RSK_KEYRINGS)) {
AddItemToPool(PendingJunkPool, RG_HIDEOUT_KEY_RING); AddItemToPool(PendingJunkPool, RG_HIDEOUT_KEY_RING);
} else { } else {
AddItemToPool(PendingJunkPool, RG_HIDEOUT_SMALL_KEY); AddItemToPool(PendingJunkPool, RG_HIDEOUT_SMALL_KEY);
@ -964,7 +856,8 @@ void GenerateItemPool() {
} }
// Gerudo Membership Card // Gerudo Membership Card
if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD) && ctx->GetOption(RSK_GERUDO_FORTRESS).IsNot(RO_GF_CARPENTERS_FREE)) { if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD) &&
ctx->GetOption(RSK_GERUDO_FORTRESS).IsNot(RO_GF_CARPENTERS_FREE)) {
AddItemToMainPool(RG_GERUDO_MEMBERSHIP_CARD); AddItemToMainPool(RG_GERUDO_MEMBERSHIP_CARD);
ctx->possibleIceTrapModels.push_back(RG_GERUDO_MEMBERSHIP_CARD); ctx->possibleIceTrapModels.push_back(RG_GERUDO_MEMBERSHIP_CARD);
} else if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { } else if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
@ -999,7 +892,9 @@ void GenerateItemPool() {
} }
// Plentiful small keys // Plentiful small keys
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) { if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) ||
ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) ||
ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
if (ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->HasKeyRing()) { if (ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->HasKeyRing()) {
AddItemToPool(PendingJunkPool, RG_BOTW_KEY_RING); AddItemToPool(PendingJunkPool, RG_BOTW_KEY_RING);
} else { } else {
@ -1042,7 +937,9 @@ void GenerateItemPool() {
} }
} }
if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) || ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) { if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) ||
ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) ||
ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
AddItemToPool(PendingJunkPool, RG_FOREST_TEMPLE_BOSS_KEY); AddItemToPool(PendingJunkPool, RG_FOREST_TEMPLE_BOSS_KEY);
AddItemToPool(PendingJunkPool, RG_FIRE_TEMPLE_BOSS_KEY); AddItemToPool(PendingJunkPool, RG_FIRE_TEMPLE_BOSS_KEY);
AddItemToPool(PendingJunkPool, RG_WATER_TEMPLE_BOSS_KEY); AddItemToPool(PendingJunkPool, RG_WATER_TEMPLE_BOSS_KEY);
@ -1050,7 +947,9 @@ void GenerateItemPool() {
AddItemToPool(PendingJunkPool, RG_SHADOW_TEMPLE_BOSS_KEY); AddItemToPool(PendingJunkPool, RG_SHADOW_TEMPLE_BOSS_KEY);
} }
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANYWHERE) || ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON) || ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) { if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANYWHERE) ||
ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON) ||
ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) {
AddItemToPool(PendingJunkPool, RG_GANONS_CASTLE_BOSS_KEY); AddItemToPool(PendingJunkPool, RG_GANONS_CASTLE_BOSS_KEY);
} }
} }
@ -1083,13 +982,9 @@ void GenerateItemPool() {
} }
// Shopsanity // Shopsanity
if ( if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF) ||
ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF) || (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_SPECIFIC_COUNT) &&
( ctx->GetOption(RSK_SHOPSANITY_COUNT).Is(RO_SHOPSANITY_COUNT_ZERO_ITEMS))) {
ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_SPECIFIC_COUNT) &&
ctx->GetOption(RSK_SHOPSANITY_COUNT).Is(RO_SHOPSANITY_COUNT_ZERO_ITEMS)
)
) {
AddItemsToPool(ItemPool, normalRupees); AddItemsToPool(ItemPool, normalRupees);
} else { } else {
AddItemsToPool(ItemPool, shopsanityRupees); // Shopsanity gets extra large rupees AddItemsToPool(ItemPool, shopsanityRupees); // Shopsanity gets extra large rupees
@ -1222,8 +1117,8 @@ void GenerateItemPool() {
uint8_t bottleCount = 4; uint8_t bottleCount = 4;
std::vector<RandomizerGet> bottles; std::vector<RandomizerGet> bottles;
bottles.assign(normalBottles.begin(), normalBottles.end()); bottles.assign(normalBottles.begin(), normalBottles.end());
ctx->possibleIceTrapModels.push_back( ctx->possibleIceTrapModels.push_back(Rando::StaticData::RetrieveItem(RandomElement(bottles))
Rando::StaticData::RetrieveItem(RandomElement(bottles)).GetRandomizerGet()); // Get one random bottle type for ice traps .GetRandomizerGet()); // Get one random bottle type for ice traps
for (uint8_t i = 0; i < bottleCount; i++) { for (uint8_t i = 0; i < bottleCount; i++) {
if (i >= rutoBottles) { if (i >= rutoBottles) {
if ((i == bottleCount - 1) && if ((i == bottleCount - 1) &&
@ -1240,7 +1135,8 @@ void GenerateItemPool() {
// add extra songs only if song shuffle is anywhere // add extra songs only if song shuffle is anywhere
AddItemsToPool(ItemPool, songList); AddItemsToPool(ItemPool, songList);
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE) && ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE) &&
ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
AddItemsToPool(PendingJunkPool, songList); AddItemsToPool(PendingJunkPool, songList);
} }

View file

@ -35,9 +35,7 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
int count; int count;
try { try {
count = std::stoi(seedInput.substr(18), nullptr); count = std::stoi(seedInput.substr(18), nullptr);
} catch (std::invalid_argument &e) { } catch (std::invalid_argument& e) { count = 1; } catch (std::out_of_range& e) {
count = 1;
} catch (std::out_of_range &e) {
count = 1; count = 1;
} }
Playthrough::Playthrough_Repeat(excludedLocations, enabledTricks, count); Playthrough::Playthrough_Repeat(excludedLocations, enabledTricks, count);

View file

@ -15,7 +15,8 @@
namespace Playthrough { namespace Playthrough {
int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks) { int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
std::set<RandomizerTrick> enabledTricks) {
// initialize the RNG with just the seed incase any settings need to be // initialize the RNG with just the seed incase any settings need to be
// resolved to something random // resolved to something random
Random_Init(seed); Random_Init(seed);
@ -65,7 +66,6 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
Random_Init(finalHash); Random_Init(finalHash);
ctx->SetHash(std::to_string(finalHash)); ctx->SetHash(std::to_string(finalHash));
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) { if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
VanillaFill(); // Just place items in their vanilla locations VanillaFill(); // Just place items in their vanilla locations
} else { // Fill locations with logic } else { // Fill locations with logic
@ -78,7 +78,8 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
GenerateHash(); GenerateHash();
if (true) { if (true) {
//TODO: Handle different types of file output (i.e. Spoiler Log, Plando Template, Patch Files, Race Files, etc.) // TODO: Handle different types of file output (i.e. Spoiler Log, Plando Template, Patch Files, Race Files,
// etc.)
// write logs // write logs
SPDLOG_INFO("Writing Spoiler Log..."); SPDLOG_INFO("Writing Spoiler Log...");
StartPerformanceTimer(PT_SPOILER_LOG); StartPerformanceTimer(PT_SPOILER_LOG);
@ -97,7 +98,8 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
} }
// used for generating a lot of seeds at once // used for generating a lot of seeds at once
int Playthrough_Repeat(std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks, int count /*= 1*/) { int Playthrough_Repeat(std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks,
int count /*= 1*/) {
SPDLOG_INFO("GENERATING {} SEEDS", count); SPDLOG_INFO("GENERATING {} SEEDS", count);
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
uint32_t repeatedSeed = 0; uint32_t repeatedSeed = 0;

View file

@ -10,16 +10,11 @@
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include "z64item.h" #include "z64item.h"
PriceSettingsStruct::PriceSettingsStruct(RandomizerSettingKey _main, PriceSettingsStruct::PriceSettingsStruct(RandomizerSettingKey _main, RandomizerSettingKey _fixedPrice,
RandomizerSettingKey _fixedPrice, RandomizerSettingKey _range1, RandomizerSettingKey _range2,
RandomizerSettingKey _range1, RandomizerSettingKey _noWallet, RandomizerSettingKey _childWallet,
RandomizerSettingKey _range2, RandomizerSettingKey _adultWallet, RandomizerSettingKey _giantWallet,
RandomizerSettingKey _noWallet, RandomizerSettingKey _tycoonWallet, RandomizerSettingKey _affordable) {
RandomizerSettingKey _childWallet,
RandomizerSettingKey _adultWallet,
RandomizerSettingKey _giantWallet,
RandomizerSettingKey _tycoonWallet,
RandomizerSettingKey _affordable){
main = _main; main = _main;
fixedPrice = _fixedPrice; fixedPrice = _fixedPrice;
range1 = _range1; range1 = _range1;
@ -32,7 +27,6 @@ PriceSettingsStruct::PriceSettingsStruct(RandomizerSettingKey _main,
affordable = _affordable; affordable = _affordable;
} }
static std::array<std::vector<Text>, 0xF1> trickNameTable; // Table of trick names for ice traps static std::array<std::vector<Text>, 0xF1> trickNameTable; // Table of trick names for ice traps
bool initTrickNames = false; // Indicates if trick ice trap names have been initialized yet bool initTrickNames = false; // Indicates if trick ice trap names have been initialized yet
@ -46,84 +40,35 @@ void PlaceVanillaShopItems() {
} }
// These are the vanilla shop items, but in a priority order of importance // These are the vanilla shop items, but in a priority order of importance
//However many shop item slots were cleared, this will return 64 minus that number of vanilla shop items to be placed with assumed fill // However many shop item slots were cleared, this will return 64 minus that number of vanilla shop items to be placed
//The first 32 items here will always be present in shops // with assumed fill The first 32 items here will always be present in shops Shopsanity 4 will only have the first 32,
//Shopsanity 4 will only have the first 32, shopsanity 1 will have the first 56, etc. // shopsanity 1 will have the first 56, etc. Shopsanity random will have anywhere from the first 32 to the first 56, so
//Shopsanity random will have anywhere from the first 32 to the first 56, so the order of items after 32 is relevant // the order of items after 32 is relevant
std::vector<RandomizerGet> GetMinVanillaShopItems(int total_replaced) { std::vector<RandomizerGet> GetMinVanillaShopItems(int total_replaced) {
std::vector<RandomizerGet> minShopItems = { std::vector<RandomizerGet> minShopItems = {
RG_BUY_DEKU_SHIELD, RG_BUY_DEKU_SHIELD, RG_BUY_HYLIAN_SHIELD, RG_BUY_GORON_TUNIC, RG_BUY_ZORA_TUNIC, RG_BUY_DEKU_NUTS_5,
RG_BUY_HYLIAN_SHIELD, RG_BUY_BOMBS_20, RG_BUY_BOMBCHUS_10, RG_BUY_DEKU_STICK_1,
RG_BUY_GORON_TUNIC,
RG_BUY_ZORA_TUNIC,
RG_BUY_DEKU_NUTS_5,
RG_BUY_BOMBS_20,
RG_BUY_BOMBCHUS_10,
RG_BUY_DEKU_STICK_1,
//^First 8 items: Exist on shopsanity 7 or less //^First 8 items: Exist on shopsanity 7 or less
RG_BUY_FAIRYS_SPIRIT, RG_BUY_FAIRYS_SPIRIT, RG_BUY_DEKU_SEEDS_30, RG_BUY_ARROWS_10, RG_BUY_BLUE_FIRE, RG_BUY_RED_POTION_30,
RG_BUY_DEKU_SEEDS_30, RG_BUY_GREEN_POTION, RG_BUY_DEKU_NUTS_10, RG_BUY_BOMBCHUS_10,
RG_BUY_ARROWS_10,
RG_BUY_BLUE_FIRE,
RG_BUY_RED_POTION_30,
RG_BUY_GREEN_POTION,
RG_BUY_DEKU_NUTS_10,
RG_BUY_BOMBCHUS_10,
//^First 16 items: Exist on shopsanity 6 or less //^First 16 items: Exist on shopsanity 6 or less
RG_BUY_BOMBCHUS_10, RG_BUY_BOMBCHUS_10, RG_BUY_BOMBCHUS_20, RG_BUY_BOMBS_525, RG_BUY_BOMBS_535, RG_BUY_BOMBS_10, RG_BUY_DEKU_NUTS_5,
RG_BUY_BOMBCHUS_20, RG_BUY_ARROWS_30, RG_BUY_ARROWS_50,
RG_BUY_BOMBS_525,
RG_BUY_BOMBS_535,
RG_BUY_BOMBS_10,
RG_BUY_DEKU_NUTS_5,
RG_BUY_ARROWS_30,
RG_BUY_ARROWS_50,
//^First 24 items: Exist on shopsanity 5 or less //^First 24 items: Exist on shopsanity 5 or less
RG_BUY_ARROWS_10, RG_BUY_ARROWS_10, RG_BUY_FAIRYS_SPIRIT, RG_BUY_BOTTLE_BUG, RG_BUY_FISH,
RG_BUY_FAIRYS_SPIRIT,
RG_BUY_BOTTLE_BUG,
RG_BUY_FISH,
//^First 28 items from OoTR //^First 28 items from OoTR
RG_BUY_HYLIAN_SHIELD, RG_BUY_HYLIAN_SHIELD, RG_BUY_BOTTLE_BUG, RG_BUY_DEKU_STICK_1, RG_BUY_DEKU_STICK_1,
RG_BUY_BOTTLE_BUG,
RG_BUY_DEKU_STICK_1,
RG_BUY_DEKU_STICK_1,
//^First 32 items: Exist on shopsanity 4 or less //^First 32 items: Exist on shopsanity 4 or less
RG_BUY_BLUE_FIRE, RG_BUY_BLUE_FIRE, RG_BUY_FISH, RG_BUY_BOMBCHUS_10, RG_BUY_DEKU_NUTS_5, RG_BUY_ARROWS_10, RG_BUY_BOMBCHUS_20,
RG_BUY_FISH, RG_BUY_BOMBS_535, RG_BUY_RED_POTION_30,
RG_BUY_BOMBCHUS_10,
RG_BUY_DEKU_NUTS_5,
RG_BUY_ARROWS_10,
RG_BUY_BOMBCHUS_20,
RG_BUY_BOMBS_535,
RG_BUY_RED_POTION_30,
//^First 40 items: Exist on shopsanity 3 or less //^First 40 items: Exist on shopsanity 3 or less
RG_BUY_BOMBS_30, RG_BUY_BOMBS_30, RG_BUY_BOMBCHUS_20, RG_BUY_DEKU_NUTS_5, RG_BUY_ARROWS_10, RG_BUY_DEKU_NUTS_5, RG_BUY_ARROWS_30,
RG_BUY_BOMBCHUS_20, RG_BUY_RED_POTION_40, RG_BUY_FISH,
RG_BUY_DEKU_NUTS_5,
RG_BUY_ARROWS_10,
RG_BUY_DEKU_NUTS_5,
RG_BUY_ARROWS_30,
RG_BUY_RED_POTION_40,
RG_BUY_FISH,
//^First 48 items: Exist on shopsanity 2 or less //^First 48 items: Exist on shopsanity 2 or less
RG_BUY_BOMBCHUS_20, RG_BUY_BOMBCHUS_20, RG_BUY_ARROWS_30, RG_BUY_RED_POTION_50, RG_BUY_ARROWS_30, RG_BUY_DEKU_NUTS_5,
RG_BUY_ARROWS_30, RG_BUY_ARROWS_50, RG_BUY_ARROWS_50, RG_BUY_GREEN_POTION,
RG_BUY_RED_POTION_50,
RG_BUY_ARROWS_30,
RG_BUY_DEKU_NUTS_5,
RG_BUY_ARROWS_50,
RG_BUY_ARROWS_50,
RG_BUY_GREEN_POTION,
//^First 56 items: Exist on shopsanity 1 or less //^First 56 items: Exist on shopsanity 1 or less
RG_BUY_POE, RG_BUY_POE, RG_BUY_POE, RG_BUY_HEART, RG_BUY_HEART, RG_BUY_HEART, RG_BUY_HEART, RG_BUY_HEART, RG_BUY_HEART,
RG_BUY_POE,
RG_BUY_HEART,
RG_BUY_HEART,
RG_BUY_HEART,
RG_BUY_HEART,
RG_BUY_HEART,
RG_BUY_HEART,
//^All 64 items: Only exist with shopsanity 0 //^All 64 items: Only exist with shopsanity 0
}; };
// Now delete however many items there are to replace // Now delete however many items there are to replace
@ -135,18 +80,20 @@ std::vector<RandomizerGet> GetMinVanillaShopItems(int total_replaced) {
// This table contains a cumulative probability for each possible shop price based on // This table contains a cumulative probability for each possible shop price based on
// a beta distribution with alpha = 1.5, beta = 2, and the result of the distribution, a float in [0.0, 1.0), // a beta distribution with alpha = 1.5, beta = 2, and the result of the distribution, a float in [0.0, 1.0),
// being mutliplied by 60, casted to an integer, then multiplied by 5 to give a value in range [0, 295] in increments of 5. // being mutliplied by 60, casted to an integer, then multiplied by 5 to give a value in range [0, 295] in increments
// Meaning the first value is the probability of 0, the next value is the probability of 0 plus the probability of 5, etc. // of 5. Meaning the first value is the probability of 0, the next value is the probability of 0 plus the probability
// of 5, etc.
// Probabilities generated using a python script with 1 billion trials, so should hopefully be pretty good // Probabilities generated using a python script with 1 billion trials, so should hopefully be pretty good
// Average price ~126 // Average price ~126
//~38% chance of needing no wallet, ~45% chance of needing 1, ~17% chance of needing 2 //~38% chance of needing no wallet, ~45% chance of needing 1, ~17% chance of needing 2
static constexpr std::array<double, 60> ShopPriceProbability = { static constexpr std::array<double, 60> ShopPriceProbability = {
0.005326994, 0.014908518, 0.027114719, 0.041315285, 0.057136304, 0.074325887, 0.092667151, 0.112002061, 0.132198214, 0.153125390, 0.005326994, 0.014908518, 0.027114719, 0.041315285, 0.057136304, 0.074325887, 0.092667151, 0.112002061, 0.132198214,
0.174696150, 0.196810540, 0.219388148, 0.242361379, 0.265657012, 0.289205134, 0.312970402, 0.336877590, 0.360881110, 0.384932772, 0.153125390, 0.174696150, 0.196810540, 0.219388148, 0.242361379, 0.265657012, 0.289205134, 0.312970402, 0.336877590,
0.408976198, 0.432982176, 0.456902494, 0.480686053, 0.504313389, 0.527746488, 0.550938554, 0.573856910, 0.596465330, 0.618736235, 0.360881110, 0.384932772, 0.408976198, 0.432982176, 0.456902494, 0.480686053, 0.504313389, 0.527746488, 0.550938554,
0.640646600, 0.662162782, 0.683240432, 0.703859801, 0.724001242, 0.743631336, 0.762722631, 0.781259986, 0.799198449, 0.816521905, 0.573856910, 0.596465330, 0.618736235, 0.640646600, 0.662162782, 0.683240432, 0.703859801, 0.724001242, 0.743631336,
0.833208595, 0.849243398, 0.864579161, 0.879211177, 0.893112051, 0.906263928, 0.918639420, 0.930222611, 0.940985829, 0.950914731, 0.762722631, 0.781259986, 0.799198449, 0.816521905, 0.833208595, 0.849243398, 0.864579161, 0.879211177, 0.893112051,
0.959992180, 0.968187000, 0.975495390, 0.981884488, 0.987344345, 0.991851853, 0.995389113, 0.997937921, 0.999481947, 1.000000000, 0.906263928, 0.918639420, 0.930222611, 0.940985829, 0.950914731, 0.959992180, 0.968187000, 0.975495390, 0.981884488,
0.987344345, 0.991851853, 0.995389113, 0.997937921, 0.999481947, 1.000000000,
}; };
// Generate random number from 5 to wallet max // Generate random number from 5 to wallet max
@ -166,8 +113,8 @@ uint16_t GetPriceFromSettings(Rando::Location *loc, PriceSettingsStruct priceSet
double random = RandomDouble(); // Randomly generated probability value double random = RandomDouble(); // Randomly generated probability value
for (size_t i = 0; i < ShopPriceProbability.size(); i++) { for (size_t i = 0; i < ShopPriceProbability.size(); i++) {
if (random < ShopPriceProbability[i]) { if (random < ShopPriceProbability[i]) {
// The randomly generated value has surpassed the total probability up to this point, so this is the generated price // The randomly generated value has surpassed the total probability up to this point, so this is the
// i in range [0, 59], output in range [0, 295] in increments of 5 // generated price i in range [0, 59], output in range [0, 295] in increments of 5
return i * 5; return i * 5;
} }
} }
@ -211,7 +158,8 @@ uint16_t GetPriceFromSettings(Rando::Location *loc, PriceSettingsStruct priceSet
return Random(501, 999); return Random(501, 999);
} }
} }
SPDLOG_ERROR("GetPriceFromSettings has failed to return a price for location {}, assigning a default value.", loc->GetName()); SPDLOG_ERROR("GetPriceFromSettings has failed to return a price for location {}, assigning a default value.",
loc->GetName());
assert(false); assert(false);
return 69; // this should never happen, if it does, EASTER EGG that tells us something is wrong return 69; // this should never happen, if it does, EASTER EGG that tells us something is wrong
} }
@ -239,8 +187,9 @@ uint16_t GetRandomPrice(Rando::Location *loc, PriceSettingsStruct priceSettings)
// multiplied by 20 instead of 60 to give values in rage [0, 95] in increments of 5 // multiplied by 20 instead of 60 to give values in rage [0, 95] in increments of 5
// Average price ~31 // Average price ~31
static constexpr std::array<double, 20> CheapPriceProbability = { static constexpr std::array<double, 20> CheapPriceProbability = {
0.097500187, 0.190002748, 0.277509301, 0.360018376, 0.437522571, 0.510021715, 0.577520272, 0.640029304, 0.697527584, 0.750024535, 0.097500187, 0.190002748, 0.277509301, 0.360018376, 0.437522571, 0.510021715, 0.577520272,
0.797518749, 0.840011707, 0.877508776, 0.910010904, 0.937504342, 0.960004661, 0.977502132, 0.989998967, 0.997500116, 1.000000000, 0.640029304, 0.697527584, 0.750024535, 0.797518749, 0.840011707, 0.877508776, 0.910010904,
0.937504342, 0.960004661, 0.977502132, 0.989998967, 0.997500116, 1.000000000,
}; };
uint16_t GetCheapBalancedPrice() { uint16_t GetCheapBalancedPrice() {
@ -581,7 +530,8 @@ void InitTrickNames() {
trickNameTable[RG_PROGRESSIVE_STICK_BAG] = { trickNameTable[RG_PROGRESSIVE_STICK_BAG] = {
Text{ "Progressive Stick Bag", "Sac de bâtons (prog.)", "Mayor capacidad de ramas deku" }, Text{ "Progressive Stick Bag", "Sac de bâtons (prog.)", "Mayor capacidad de ramas deku" },
Text{ "Progressive Stick Pack", "Paquet de bâtons Mojo (prog.)", "Mayor capacidad de bastones" }, Text{ "Progressive Stick Pack", "Paquet de bâtons Mojo (prog.)", "Mayor capacidad de bastones" },
Text{"Progressive Branch Capacity", "Capacité de la succursale (prog.)", "Capacidad progresiva de la sucursal"}, Text{ "Progressive Branch Capacity", "Capacité de la succursale (prog.)",
"Capacidad progresiva de la sucursal" },
Text{ "Progressive Rod Capacity", "Capacité de tiges (prog.)", "Mayor capacidad de cetros deku" }, Text{ "Progressive Rod Capacity", "Capacité de tiges (prog.)", "Mayor capacidad de cetros deku" },
}; };
trickNameTable[RG_PROGRESSIVE_BOMBCHUS] = { trickNameTable[RG_PROGRESSIVE_BOMBCHUS] = {
@ -623,7 +573,8 @@ void InitTrickNames() {
Text{ "Bottle with Chateau Romani", "Flacon de cuvée Romani", "Botella de Reserva Romani" }, Text{ "Bottle with Chateau Romani", "Flacon de cuvée Romani", "Botella de Reserva Romani" },
Text{ "Bottle with Premium Milk", "Flacon avec lait de qualité supérieure", "Biberón con leche Premium" }, Text{ "Bottle with Premium Milk", "Flacon avec lait de qualité supérieure", "Biberón con leche Premium" },
Text{ "Bottle with Mystery Milk", "Flacon de lait grand cru", "Botella de leche extra" }, Text{ "Bottle with Mystery Milk", "Flacon de lait grand cru", "Botella de leche extra" },
Text{"Bottle with Fresh Milk", "Flacon de lait frais", "Botella de leche fresca"},}; Text{ "Bottle with Fresh Milk", "Flacon de lait frais", "Botella de leche fresca" },
};
trickNameTable[RG_BOTTLE_WITH_RED_POTION] = { trickNameTable[RG_BOTTLE_WITH_RED_POTION] = {
Text{ "Bottle with Red Chu Jelly", "Flacon de gelée Chuchu rouge", "Jugo de Chuchu Rojo" }, Text{ "Bottle with Red Chu Jelly", "Flacon de gelée Chuchu rouge", "Jugo de Chuchu Rojo" },
Text{ "Bottle with Hibiscus Potion", "Flacon de potion de Hibiscus", "Botella de poción de Hibisco" }, Text{ "Bottle with Hibiscus Potion", "Flacon de potion de Hibiscus", "Botella de poción de Hibisco" },
@ -811,10 +762,8 @@ void InitTrickNames() {
Text{ "HP", "VP", "VP" }, Text{ "HP", "VP", "VP" },
}; };
trickNameTable[RG_GREEN_RUPEE] = { trickNameTable[RG_GREEN_RUPEE] = {
Text{"False Greg", "Faux Greg", "Falso Greg"}, Text{ "False Greg", "Faux Greg", "Falso Greg" }, Text{ "One Ruby", "Un rubis", "Un rubí" },
Text{"One Ruby", "Un rubis", "Un rubí"}, Text{ "Rupoor (1)", "Roupir (1)", "Rupobre (1)" }, Text{ "One Rupee", "Un rubis", "Guaraní hyliano" },
Text{"Rupoor (1)", "Roupir (1)", "Rupobre (1)"},
Text{"One Rupee", "Un rubis", "Guaraní hyliano"},
Text{ "Rupee (1)", "Rubis (1)", "Peso hyliano" }, Text{ "Rupee (1)", "Rubis (1)", "Peso hyliano" },
}; };
trickNameTable[RG_BLUE_RUPEE] = { trickNameTable[RG_BLUE_RUPEE] = {
@ -825,10 +774,8 @@ void InitTrickNames() {
Text{ "Rupoor (5)", "Roupir (5)", "Rupobre (5)" }, Text{ "Rupoor (5)", "Roupir (5)", "Rupobre (5)" },
}; };
trickNameTable[RG_RED_RUPEE] = { trickNameTable[RG_RED_RUPEE] = {
Text{"Big 20", "Grand 20", "Los 20 grandes"}, Text{ "Big 20", "Grand 20", "Los 20 grandes" }, Text{ "Twenty Rubies", "vingt rubis", "Veinte rubíes" },
Text{"Twenty Rubies", "vingt rubis", "Veinte rubíes"}, Text{ "Rupoor (20)", "Roupir (20)", "Rupobre (20)" }, Text{ "Twenty Rupees", "Vingt rubis", "Colon hyliano" },
Text{"Rupoor (20)", "Roupir (20)", "Rupobre (20)"},
Text{"Twenty Rupees", "Vingt rubis", "Colon hyliano"},
Text{ "Rupee (20)", "Rubis (20)", "Peso hyliano" }, Text{ "Rupee (20)", "Rubis (20)", "Peso hyliano" },
}; };
trickNameTable[RG_PURPLE_RUPEE] = { trickNameTable[RG_PURPLE_RUPEE] = {

View file

@ -70,8 +70,7 @@ static auto GetPlacementLogPath() {
} }
// Writes the location to the specified node. // Writes the location to the specified node.
static void WriteLocation( static void WriteLocation(std::string sphere, const RandomizerCheck locationKey, const bool withPadding = false) {
std::string sphere, const RandomizerCheck locationKey, const bool withPadding = false) {
Rando::Location* location = Rando::StaticData::GetLocation(locationKey); Rando::Location* location = Rando::StaticData::GetLocation(locationKey);
Rando::ItemLocation* itemLocation = Rando::Context::GetInstance()->GetItemLocation(locationKey); Rando::ItemLocation* itemLocation = Rando::Context::GetInstance()->GetItemLocation(locationKey);
@ -156,7 +155,6 @@ static void WriteExcludedLocations() {
} }
jsonData["excludedLocations"].push_back(RemoveLineBreaks(location->GetName())); jsonData["excludedLocations"].push_back(RemoveLineBreaks(location->GetName()));
} }
} }
} }
@ -221,7 +219,8 @@ static void WritePlaythrough() {
for (uint32_t i = 0; i < ctx->playthroughLocations.size(); ++i) { for (uint32_t i = 0; i < ctx->playthroughLocations.size(); ++i) {
auto sphereNum = std::to_string(i); auto sphereNum = std::to_string(i);
std::string sphereString = "sphere "; std::string sphereString = "sphere ";
if (i < 10) sphereString += "0"; if (i < 10)
sphereString += "0";
sphereString += sphereNum; sphereString += sphereNum;
for (const RandomizerCheck key : ctx->playthroughLocations[i]) { for (const RandomizerCheck key : ctx->playthroughLocations[i]) {
WriteLocation(sphereString, key, true); WriteLocation(sphereString, key, true);
@ -235,7 +234,8 @@ static void WriteShuffledEntrances() {
for (uint32_t i = 0; i < ctx->GetEntranceShuffler()->playthroughEntrances.size(); ++i) { for (uint32_t i = 0; i < ctx->GetEntranceShuffler()->playthroughEntrances.size(); ++i) {
auto sphereNum = std::to_string(i); auto sphereNum = std::to_string(i);
std::string sphereString = "sphere "; std::string sphereString = "sphere ";
if (i < 10) sphereString += "0"; if (i < 10)
sphereString += "0";
sphereString += sphereNum; sphereString += sphereNum;
for (Entrance* entrance : ctx->GetEntranceShuffler()->playthroughEntrances[i]) { for (Entrance* entrance : ctx->GetEntranceShuffler()->playthroughEntrances[i]) {
WriteShuffledEntrance(sphereString, entrance); WriteShuffledEntrance(sphereString, entrance);
@ -258,15 +258,16 @@ static void WriteAllLocations() {
// If it's a simple item (not an ice trap, doesn't have a price) // If it's a simple item (not an ice trap, doesn't have a price)
// just add the name of the item and move on // just add the name of the item and move on
if (!location->HasCustomPrice() && if (!location->HasCustomPrice() && location->GetPlacedRandomizerGet() != RG_ICE_TRAP) {
location->GetPlacedRandomizerGet() != RG_ICE_TRAP) {
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()] = placedItemName; jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()] =
placedItemName;
continue; continue;
} }
// We're dealing with a complex item, build out the json object for it // We're dealing with a complex item, build out the json object for it
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["item"] = placedItemName; jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["item"] =
placedItemName;
if (location->HasCustomPrice()) { if (location->HasCustomPrice()) {
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["price"] = jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["price"] =
@ -364,4 +365,3 @@ void PlacementLog_Msg(std::string_view msg) {
void PlacementLog_Clear() { void PlacementLog_Clear() {
placementtxt = ""; placementtxt = "";
} }

View file

@ -56,12 +56,12 @@ void GenerateStartingInventory() {
// Add Ganon's Boss key with Triforce Hunt so the game thinks it's obtainable from the start. // Add Ganon's Boss key with Triforce Hunt so the game thinks it's obtainable from the start.
// During save init, the boss key isn't actually given and it's instead given when completing the triforce. // During save init, the boss key isn't actually given and it's instead given when completing the triforce.
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH) || if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH) || ctx->GetOption(RSK_TRIFORCE_HUNT)) {
ctx->GetOption(RSK_TRIFORCE_HUNT)) {
AddItemToInventory(RG_GANONS_CASTLE_BOSS_KEY); AddItemToInventory(RG_GANONS_CASTLE_BOSS_KEY);
} }
if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) && !ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) &&
!ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
AddItemToInventory(RG_GERUDO_MEMBERSHIP_CARD); AddItemToInventory(RG_GERUDO_MEMBERSHIP_CARD);
} }

View file

@ -15,10 +15,12 @@ extern "C" {
#define CVAR_COLORED_MAPS_AND_COMPASSES_NAME CVAR_RANDOMIZER_ENHANCEMENT("ColoredMapsAndCompasses") #define CVAR_COLORED_MAPS_AND_COMPASSES_NAME CVAR_RANDOMIZER_ENHANCEMENT("ColoredMapsAndCompasses")
#define CVAR_COLORED_MAPS_AND_COMPASSES_DEFAULT 1 #define CVAR_COLORED_MAPS_AND_COMPASSES_DEFAULT 1
#define CVAR_COLORED_MAPS_AND_COMPASSES_VALUE CVarGetInteger(CVAR_COLORED_MAPS_AND_COMPASSES_NAME, CVAR_COLORED_MAPS_AND_COMPASSES_DEFAULT) #define CVAR_COLORED_MAPS_AND_COMPASSES_VALUE \
CVarGetInteger(CVAR_COLORED_MAPS_AND_COMPASSES_NAME, CVAR_COLORED_MAPS_AND_COMPASSES_DEFAULT)
void OnLoadFileColoredMapsAndCompasses(int32_t _) { void OnLoadFileColoredMapsAndCompasses(int32_t _) {
s8 mapsAndCompassesCanBeOutsideDungeon = IS_RANDO && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS); s8 mapsAndCompassesCanBeOutsideDungeon =
IS_RANDO && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS);
s8 isColoredMapsAndCompassesEnabled = mapsAndCompassesCanBeOutsideDungeon && CVAR_COLORED_MAPS_AND_COMPASSES_VALUE; s8 isColoredMapsAndCompassesEnabled = mapsAndCompassesCanBeOutsideDungeon && CVAR_COLORED_MAPS_AND_COMPASSES_VALUE;
if (isColoredMapsAndCompassesEnabled) { if (isColoredMapsAndCompassesEnabled) {
ResourceMgr_PatchGfxByName(gGiDungeonMapDL, "Map_PrimColor", 5, gsDPNoOp()); ResourceMgr_PatchGfxByName(gGiDungeonMapDL, "Map_PrimColor", 5, gsDPNoOp());

View file

@ -93,7 +93,8 @@ void RegisterLockOverworldDoors() {
COND_VB_SHOULD(VB_CONSUME_SMALL_KEY, shouldRegister, { COND_VB_SHOULD(VB_CONSUME_SMALL_KEY, shouldRegister, {
EnDoor* enDoor = va_arg(args, EnDoor*); EnDoor* enDoor = va_arg(args, EnDoor*);
if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED && enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) { if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED &&
enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) {
Flags_SetRandomizerInf(enDoor->randomizerInf); Flags_SetRandomizerInf(enDoor->randomizerInf);
*should = false; *should = false;
} }
@ -102,7 +103,8 @@ void RegisterLockOverworldDoors() {
COND_VB_SHOULD(VB_NOT_HAVE_SMALL_KEY, shouldRegister, { COND_VB_SHOULD(VB_NOT_HAVE_SMALL_KEY, shouldRegister, {
EnDoor* enDoor = va_arg(args, EnDoor*); EnDoor* enDoor = va_arg(args, EnDoor*);
if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED && enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) { if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED &&
enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) {
*should = !Flags_GetRandomizerInf((RandomizerInf)(enDoor->randomizerInf + 1)); *should = !Flags_GetRandomizerInf((RandomizerInf)(enDoor->randomizerInf + 1));
} }
}); });
@ -110,21 +112,20 @@ void RegisterLockOverworldDoors() {
COND_VB_SHOULD(VB_DOOR_BE_LOCKED, shouldRegister, { COND_VB_SHOULD(VB_DOOR_BE_LOCKED, shouldRegister, {
EnDoor* enDoor = va_arg(args, EnDoor*); EnDoor* enDoor = va_arg(args, EnDoor*);
if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED && enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) { if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED &&
enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) {
*should = !Flags_GetRandomizerInf(enDoor->randomizerInf); *should = !Flags_GetRandomizerInf(enDoor->randomizerInf);
} }
}); });
// The door actor uses the same param to indicate if a door should be locked or be a scene transition, so it cannot be both. Here we're // The door actor uses the same param to indicate if a door should be locked or be a scene transition, so it cannot
// overriding the check for scene transition to also check if the door is being unlocked and should be a scene transition. // be both. Here we're overriding the check for scene transition to also check if the door is being unlocked and
// should be a scene transition.
COND_VB_SHOULD(VB_DOOR_PLAY_SCENE_TRANSITION, shouldRegister, { COND_VB_SHOULD(VB_DOOR_PLAY_SCENE_TRANSITION, shouldRegister, {
EnDoor* enDoor = va_arg(args, EnDoor*); EnDoor* enDoor = va_arg(args, EnDoor*);
if (!*should && ( if (!*should && (enDoor->actor.id == ACTOR_EN_DOOR && ((enDoor->actor.params >> 7) & 7) == 1 &&
enDoor->actor.id == ACTOR_EN_DOOR && enDoor->randomizerInf != RAND_INF_MAX)) {
((enDoor->actor.params >> 7) & 7) == 1 &&
enDoor->randomizerInf != RAND_INF_MAX
)) {
*should = true; *should = true;
} }
}); });

View file

@ -62,41 +62,29 @@ std::vector<SpoilerHintObject> plandoHintData;
extern std::map<RandomizerCheckArea, std::string> rcAreaNames; extern std::map<RandomizerCheckArea, std::string> rcAreaNames;
std::unordered_map<RandomizerGet, std::string> bossKeyShortNames = { std::unordered_map<RandomizerGet, std::string> bossKeyShortNames = {
{ RG_FOREST_TEMPLE_BOSS_KEY, "Frst" }, { RG_FOREST_TEMPLE_BOSS_KEY, "Frst" }, { RG_FIRE_TEMPLE_BOSS_KEY, "Fire" },
{ RG_FIRE_TEMPLE_BOSS_KEY, "Fire" }, { RG_WATER_TEMPLE_BOSS_KEY, "Watr" }, { RG_SPIRIT_TEMPLE_BOSS_KEY, "Sprt" },
{ RG_WATER_TEMPLE_BOSS_KEY, "Watr" }, { RG_SHADOW_TEMPLE_BOSS_KEY, "Shdw" }, { RG_GANONS_CASTLE_BOSS_KEY, "Ganon" },
{ RG_SPIRIT_TEMPLE_BOSS_KEY, "Sprt" },
{ RG_SHADOW_TEMPLE_BOSS_KEY, "Shdw" },
{ RG_GANONS_CASTLE_BOSS_KEY, "Ganon" },
}; };
std::unordered_map<RandomizerGet, std::string> ocarinaButtonNames = { std::unordered_map<RandomizerGet, std::string> ocarinaButtonNames = {
{ RG_OCARINA_A_BUTTON, "A" }, { RG_OCARINA_A_BUTTON, "A" }, { RG_OCARINA_C_UP_BUTTON, "C-UP" },
{ RG_OCARINA_C_UP_BUTTON, "C-UP" }, { RG_OCARINA_C_DOWN_BUTTON, "C-DWN" }, { RG_OCARINA_C_LEFT_BUTTON, "C-LFT" },
{ RG_OCARINA_C_DOWN_BUTTON, "C-DWN" },
{ RG_OCARINA_C_LEFT_BUTTON, "C-LFT" },
{ RG_OCARINA_C_RIGHT_BUTTON, "C-RHT" }, { RG_OCARINA_C_RIGHT_BUTTON, "C-RHT" },
}; };
std::map<RandomizerGet, ImVec4> bossSoulColorMapping = { std::map<RandomizerGet, ImVec4> bossSoulColorMapping = {
{ RG_GOHMA_SOUL, { 0.00f, 1.00f, 0.00f, 1.0f } }, { RG_GOHMA_SOUL, { 0.00f, 1.00f, 0.00f, 1.0f } }, { RG_KING_DODONGO_SOUL, { 1.00f, 0.00f, 0.39f, 1.0f } },
{ RG_KING_DODONGO_SOUL, { 1.00f, 0.00f, 0.39f, 1.0f } }, { RG_BARINADE_SOUL, { 0.20f, 1.00f, 1.00f, 1.0f } }, { RG_PHANTOM_GANON_SOUL, { 0.02f, 0.76f, 0.18f, 1.0f } },
{ RG_BARINADE_SOUL, { 0.20f, 1.00f, 1.00f, 1.0f } }, { RG_VOLVAGIA_SOUL, { 0.93f, 0.37f, 0.37f, 1.0f } }, { RG_MORPHA_SOUL, { 0.33f, 0.71f, 0.87f, 1.0f } },
{ RG_PHANTOM_GANON_SOUL, { 0.02f, 0.76f, 0.18f, 1.0f } }, { RG_BONGO_BONGO_SOUL, { 0.49f, 0.06f, 0.69f, 1.0f } }, { RG_TWINROVA_SOUL, { 0.87f, 0.62f, 0.18f, 1.0f } },
{ RG_VOLVAGIA_SOUL, { 0.93f, 0.37f, 0.37f, 1.0f } },
{ RG_MORPHA_SOUL, { 0.33f, 0.71f, 0.87f, 1.0f } },
{ RG_BONGO_BONGO_SOUL, { 0.49f, 0.06f, 0.69f, 1.0f } },
{ RG_TWINROVA_SOUL, { 0.87f, 0.62f, 0.18f, 1.0f } },
{ RG_GANON_SOUL, { 0.31f, 0.31f, 0.31f, 1.0f } } { RG_GANON_SOUL, { 0.31f, 0.31f, 0.31f, 1.0f } }
}; };
std::vector<RandomizerGet> infiniteItemList = { std::vector<RandomizerGet> infiniteItemList = {
RG_GREEN_RUPEE, RG_BLUE_RUPEE, RG_RED_RUPEE, RG_PURPLE_RUPEE, RG_HUGE_RUPEE, RG_GREEN_RUPEE, RG_BLUE_RUPEE, RG_RED_RUPEE, RG_PURPLE_RUPEE, RG_HUGE_RUPEE, RG_ARROWS_5, RG_ARROWS_10,
RG_ARROWS_5, RG_ARROWS_10, RG_ARROWS_30, RG_ARROWS_30, RG_DEKU_STICK_1, RG_DEKU_SEEDS_30, RG_DEKU_NUTS_5, RG_DEKU_NUTS_10, RG_BOMBS_5, RG_BOMBS_10,
RG_DEKU_STICK_1, RG_DEKU_SEEDS_30, RG_DEKU_NUTS_5, RG_DEKU_NUTS_10, RG_BOMBS_20, RG_BOMBCHU_5, RG_BOMBCHU_10, RG_BOMBCHU_20, RG_RECOVERY_HEART, RG_ICE_TRAP, RG_SOLD_OUT
RG_BOMBS_5, RG_BOMBS_10, RG_BOMBS_20, RG_BOMBCHU_5, RG_BOMBCHU_10, RG_BOMBCHU_20,
RG_RECOVERY_HEART, RG_ICE_TRAP, RG_SOLD_OUT
}; };
std::unordered_map<RandomizerGet, std::string> itemImageMap = { std::unordered_map<RandomizerGet, std::string> itemImageMap = {
@ -283,8 +271,8 @@ void PlandoPopImageButtonStyle(){
ImVec4 plandomizerGetItemColor(Rando::Item randoItem) { ImVec4 plandomizerGetItemColor(Rando::Item randoItem) {
itemColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); itemColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
if (randoItem.GetItemType() == ITEMTYPE_SMALLKEY || randoItem.GetItemType() == ITEMTYPE_HIDEOUT_KEY if (randoItem.GetItemType() == ITEMTYPE_SMALLKEY || randoItem.GetItemType() == ITEMTYPE_HIDEOUT_KEY ||
|| randoItem.GetItemType() == ITEMTYPE_BOSSKEY) { randoItem.GetItemType() == ITEMTYPE_BOSSKEY) {
if (randoItem.GetRandomizerGet() == RG_FOREST_TEMPLE_SMALL_KEY || if (randoItem.GetRandomizerGet() == RG_FOREST_TEMPLE_SMALL_KEY ||
randoItem.GetRandomizerGet() == RG_FOREST_TEMPLE_KEY_RING) { randoItem.GetRandomizerGet() == RG_FOREST_TEMPLE_KEY_RING) {
itemColor = ImVec4(0.02f, 0.76f, 0.18f, 1.0f); itemColor = ImVec4(0.02f, 0.76f, 0.18f, 1.0f);
@ -317,15 +305,16 @@ ImVec4 plandomizerGetItemColor(Rando::Item randoItem) {
} }
if (randoItem.GetItemType() == ITEMTYPE_SONG) { if (randoItem.GetItemType() == ITEMTYPE_SONG) {
uint32_t questID = Rando::Logic::RandoGetToQuestItem[randoItem.GetRandomizerGet()]; uint32_t questID = Rando::Logic::RandoGetToQuestItem[randoItem.GetRandomizerGet()];
textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(songMapping.at((QuestItem)questID).name); textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
songMapping.at((QuestItem)questID).name);
itemColor = songMapping.at((QuestItem)questID).color; itemColor = songMapping.at((QuestItem)questID).color;
imageSize = ImVec2(24.0f, 32.0f); imageSize = ImVec2(24.0f, 32.0f);
imagePadding = 6.0f; imagePadding = 6.0f;
return itemColor; return itemColor;
} }
if (randoItem.GetRandomizerGet() >= RG_GREEN_RUPEE && randoItem.GetRandomizerGet() <= RG_HUGE_RUPEE) { if (randoItem.GetRandomizerGet() >= RG_GREEN_RUPEE && randoItem.GetRandomizerGet() <= RG_HUGE_RUPEE) {
if (randoItem.GetRandomizerGet() == RG_GREG_RUPEE || randoItem.GetRandomizerGet() == RG_GREEN_RUPEE if (randoItem.GetRandomizerGet() == RG_GREG_RUPEE || randoItem.GetRandomizerGet() == RG_GREEN_RUPEE ||
|| randoItem.GetRandomizerGet() == RG_LOSER_GREEN_RUPEE) { randoItem.GetRandomizerGet() == RG_LOSER_GREEN_RUPEE) {
itemColor = ImVec4(0.02f, 0.76f, 0.18f, 1.0f); itemColor = ImVec4(0.02f, 0.76f, 0.18f, 1.0f);
} else if (randoItem.GetRandomizerGet() == RG_BLUE_RUPEE) { } else if (randoItem.GetRandomizerGet() == RG_BLUE_RUPEE) {
itemColor = ImVec4(0.33f, 0.71f, 0.87f, 1.0f); itemColor = ImVec4(0.33f, 0.71f, 0.87f, 1.0f);
@ -348,8 +337,7 @@ ImVec4 plandomizerGetItemColor(Rando::Item randoItem) {
std::string plandomizerHintsTooltip() { std::string plandomizerHintsTooltip() {
std::string hintTootip; std::string hintTootip;
hintTootip = hintTootip = "The following options are available:\n"
"The following options are available:\n"
"- Use \\n to create New Lines.\n" "- Use \\n to create New Lines.\n"
"- Use %g to change the text color to Green,\n" "- Use %g to change the text color to Green,\n"
" - %r for Red, %y for Yellow, and %w for White\n" " - %r for Red, %y for Yellow, and %w for White\n"
@ -388,7 +376,6 @@ void PlandomizerItemImageCorrection(Rando::Item randoItem) {
textureUV0 = ImVec2(0, 0); textureUV0 = ImVec2(0, 0);
textureUV1 = ImVec2(1, 1); textureUV1 = ImVec2(1, 1);
itemColor = plandomizerGetItemColor(randoItem); itemColor = plandomizerGetItemColor(randoItem);
if (randoItem.GetItemType() == ITEMTYPE_SMALLKEY || randoItem.GetItemType() == ITEMTYPE_HIDEOUT_KEY) { if (randoItem.GetItemType() == ITEMTYPE_SMALLKEY || randoItem.GetItemType() == ITEMTYPE_HIDEOUT_KEY) {
@ -419,21 +406,25 @@ void PlandomizerItemImageCorrection(Rando::Item randoItem) {
textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("BOSS_SOUL"); textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("BOSS_SOUL");
} }
if (randoItem.GetRandomizerGet() >= RG_OCARINA_A_BUTTON && randoItem.GetRandomizerGet() <= RG_OCARINA_C_RIGHT_BUTTON) { if (randoItem.GetRandomizerGet() >= RG_OCARINA_A_BUTTON &&
randoItem.GetRandomizerGet() <= RG_OCARINA_C_RIGHT_BUTTON) {
textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("ITEM_OCARINA_TIME"); textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("ITEM_OCARINA_TIME");
} }
if (textureID == 0) { if (textureID == 0) {
textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[randoItem.GetGIEntry()->itemId].name); textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
itemMapping[randoItem.GetGIEntry()->itemId].name);
} }
} }
void PlandomizerRandomizeHint(int32_t status, int32_t index) { void PlandomizerRandomizeHint(int32_t status, int32_t index) {
if (status == HINT_SINGLE) { if (status == HINT_SINGLE) {
plandoHintData[index].hintText = Rando::StaticData::hintTextTable[GetRandomJunkHint()].GetHintMessage().GetForCurrentLanguage(MF_ENCODE); plandoHintData[index].hintText =
Rando::StaticData::hintTextTable[GetRandomJunkHint()].GetHintMessage().GetForCurrentLanguage(MF_ENCODE);
} else { } else {
for (auto& hint : plandoHintData) { for (auto& hint : plandoHintData) {
hint.hintText = Rando::StaticData::hintTextTable[GetRandomJunkHint()].GetHintMessage().GetForCurrentLanguage(MF_ENCODE); hint.hintText =
Rando::StaticData::hintTextTable[GetRandomJunkHint()].GetHintMessage().GetForCurrentLanguage(MF_ENCODE);
} }
} }
} }
@ -447,8 +438,7 @@ void PlandomizerRemoveAllHints() {
} }
void PlandomizerSortDrawnItems() { void PlandomizerSortDrawnItems() {
std::sort(drawnItemsList.begin(), drawnItemsList.end(), std::sort(drawnItemsList.begin(), drawnItemsList.end(), [](const auto& a, const auto& b) {
[](const auto& a, const auto& b) {
auto typeA = a.first.GetItemType(); auto typeA = a.first.GetItemType();
auto typeB = b.first.GetItemType(); auto typeB = b.first.GetItemType();
if (typeA != typeB) { if (typeA != typeB) {
@ -463,7 +453,8 @@ void PlandomizerRemoveAllItems() {
drawnItemsList.clear(); drawnItemsList.clear();
} }
for (auto& remove : plandoLogData) { for (auto& remove : plandoLogData) {
if (std::find(infiniteItemList.begin(), infiniteItemList.end(), remove.checkRewardItem.GetRandomizerGet()) == infiniteItemList.end()) { if (std::find(infiniteItemList.begin(), infiniteItemList.end(), remove.checkRewardItem.GetRandomizerGet()) ==
infiniteItemList.end()) {
bool itemExists = false; bool itemExists = false;
for (auto& itemToCheck : drawnItemsList) { for (auto& itemToCheck : drawnItemsList) {
if (itemToCheck.first.GetRandomizerGet() == remove.checkRewardItem.GetRandomizerGet()) { if (itemToCheck.first.GetRandomizerGet() == remove.checkRewardItem.GetRandomizerGet()) {
@ -482,7 +473,8 @@ void PlandomizerRemoveAllItems() {
} }
void PlandomizerRemoveFromItemList(Rando::Item randoItem) { void PlandomizerRemoveFromItemList(Rando::Item randoItem) {
if (std::find(infiniteItemList.begin(), infiniteItemList.end(), randoItem.GetRandomizerGet()) == infiniteItemList.end()) { if (std::find(infiniteItemList.begin(), infiniteItemList.end(), randoItem.GetRandomizerGet()) ==
infiniteItemList.end()) {
uint32_t index = 0; uint32_t index = 0;
for (auto& itemToCheck : drawnItemsList) { for (auto& itemToCheck : drawnItemsList) {
if (itemToCheck.first.GetRandomizerGet() == randoItem.GetRandomizerGet()) { if (itemToCheck.first.GetRandomizerGet() == randoItem.GetRandomizerGet()) {
@ -501,7 +493,8 @@ void PlandomizerRemoveFromItemList(Rando::Item randoItem) {
} }
void PlandomizerAddToItemList(Rando::Item randoItem) { void PlandomizerAddToItemList(Rando::Item randoItem) {
if (std::find(infiniteItemList.begin(), infiniteItemList.end(), randoItem.GetRandomizerGet()) == infiniteItemList.end()) { if (std::find(infiniteItemList.begin(), infiniteItemList.end(), randoItem.GetRandomizerGet()) ==
infiniteItemList.end()) {
bool itemExists = false; bool itemExists = false;
for (auto& itemToCheck : drawnItemsList) { for (auto& itemToCheck : drawnItemsList) {
if (itemToCheck.first.GetRandomizerGet() == randoItem.GetRandomizerGet()) { if (itemToCheck.first.GetRandomizerGet() == randoItem.GetRandomizerGet()) {
@ -528,32 +521,24 @@ void PlandomizerSaveSpoilerLog() {
inputFile.close(); inputFile.close();
} }
spoilerSave["file_hash"] = { spoilerSave["file_hash"] = { plandoHash[0], plandoHash[1], plandoHash[2], plandoHash[3], plandoHash[4] };
plandoHash[0], plandoHash[1], plandoHash[2], plandoHash[3], plandoHash[4]
};
for (auto& import : plandoHintData) { for (auto& import : plandoHintData) {
spoilerSave["Gossip Stone Hints"][import.hintName] = { spoilerSave["Gossip Stone Hints"][import.hintName] = { { "type", import.hintType.c_str() },
{ "type", import.hintType.c_str() }, { "message", import.hintText.c_str() } };
{ "message", import.hintText.c_str() }
};
} }
for (auto& import : plandoLogData) { for (auto& import : plandoLogData) {
if (import.checkRewardItem.GetRandomizerGet() == RG_ICE_TRAP) { if (import.checkRewardItem.GetRandomizerGet() == RG_ICE_TRAP) {
spoilerSave["locations"][import.checkName] = { spoilerSave["locations"][import.checkName] = { { "item", import.checkRewardItem.GetName().GetForCurrentLanguage(MF_RAW) },
{ "item", import.checkRewardItem.GetName().GetForCurrentLanguage(MF_RAW) },
{ "model", import.iceTrapModel.GetName().GetForCurrentLanguage(MF_RAW) }, { "model", import.iceTrapModel.GetName().GetForCurrentLanguage(MF_RAW) },
{ "trickName", import.iceTrapName.c_str() } { "trickName", import.iceTrapName.c_str() } };
};
if (import.shopPrice > -1) { if (import.shopPrice > -1) {
spoilerSave["locations"][import.checkName]["price"] = import.shopPrice; spoilerSave["locations"][import.checkName]["price"] = import.shopPrice;
} }
} else if (import.shopPrice > -1) { } else if (import.shopPrice > -1) {
spoilerSave["locations"][import.checkName] = { spoilerSave["locations"][import.checkName] = { { "item", import.checkRewardItem.GetName().GetForCurrentLanguage(MF_RAW) },
{ "item", import.checkRewardItem.GetName().GetForCurrentLanguage(MF_RAW) }, { "price", import.shopPrice } };
{ "price", import.shopPrice }
};
} else { } else {
spoilerSave["locations"][import.checkName] = import.checkRewardItem.GetName().GetForCurrentLanguage(MF_RAW); spoilerSave["locations"][import.checkName] = import.checkRewardItem.GetName().GetForCurrentLanguage(MF_RAW);
} }
@ -621,21 +606,24 @@ void PlandomizerLoadSpoilerLog(std::string logFile) {
checkObject.checkName = key; checkObject.checkName = key;
auto type = value; auto type = value;
if (value.is_object()) { if (value.is_object()) {
checkObject.checkRewardItem = plandomizerRandoRetrieveItem(Rando::StaticData::itemNameToEnum[value["item"]]); checkObject.checkRewardItem =
plandomizerRandoRetrieveItem(Rando::StaticData::itemNameToEnum[value["item"]]);
if (value["price"].is_number()) { if (value["price"].is_number()) {
checkObject.shopPrice = value["price"]; checkObject.shopPrice = value["price"];
} else { } else {
checkObject.shopPrice = -1; checkObject.shopPrice = -1;
} }
if (checkObject.checkRewardItem.GetRandomizerGet() == RG_ICE_TRAP) { if (checkObject.checkRewardItem.GetRandomizerGet() == RG_ICE_TRAP) {
checkObject.iceTrapModel = plandomizerRandoRetrieveItem(Rando::StaticData::itemNameToEnum[value["model"]]); checkObject.iceTrapModel =
plandomizerRandoRetrieveItem(Rando::StaticData::itemNameToEnum[value["model"]]);
checkObject.iceTrapName = value["trickName"]; checkObject.iceTrapName = value["trickName"];
} }
} else { } else {
checkObject.checkRewardItem = plandomizerRandoRetrieveItem(Rando::StaticData::itemNameToEnum[value.get<std::string>()]); checkObject.checkRewardItem =
plandomizerRandoRetrieveItem(Rando::StaticData::itemNameToEnum[value.get<std::string>()]);
checkObject.shopPrice = -1; checkObject.shopPrice = -1;
if (checkObject.shopPrice == -1 if (checkObject.shopPrice == -1 &&
&& checkObject.checkRewardItem.GetItemType() == ITEMTYPE_SHOP) { checkObject.checkRewardItem.GetItemType() == ITEMTYPE_SHOP) {
checkObject.shopPrice = checkObject.checkRewardItem.GetPrice(); checkObject.shopPrice = checkObject.checkRewardItem.GetPrice();
} }
} }
@ -717,10 +705,12 @@ void PlandomizerDrawItemPopup(uint32_t index) {
PlandomizerItemImageCorrection(plandomizerRandoRetrieveItem(item)); PlandomizerItemImageCorrection(plandomizerRandoRetrieveItem(item));
auto name = plandomizerRandoRetrieveItem(item).GetName().GetForCurrentLanguage(MF_RAW); auto name = plandomizerRandoRetrieveItem(item).GetName().GetForCurrentLanguage(MF_RAW);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(imagePadding, imagePadding)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(imagePadding, imagePadding));
auto ret = ImGui::ImageButton(name.c_str(), textureID, imageSize, textureUV0, textureUV1, ImVec4(0, 0, 0, 0), itemColor); auto ret = ImGui::ImageButton(name.c_str(), textureID, imageSize, textureUV0, textureUV1,
ImVec4(0, 0, 0, 0), itemColor);
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (ret) { if (ret) {
if (std::find(infiniteItemList.begin(), infiniteItemList.end(), plandoLogData[index].checkRewardItem.GetRandomizerGet()) == infiniteItemList.end()) { if (std::find(infiniteItemList.begin(), infiniteItemList.end(),
plandoLogData[index].checkRewardItem.GetRandomizerGet()) == infiniteItemList.end()) {
PlandomizerAddToItemList(plandoLogData[index].checkRewardItem); PlandomizerAddToItemList(plandoLogData[index].checkRewardItem);
} }
plandoLogData[index].checkRewardItem = plandomizerRandoRetrieveItem(item); plandoLogData[index].checkRewardItem = plandomizerRandoRetrieveItem(item);
@ -731,7 +721,6 @@ void PlandomizerDrawItemPopup(uint32_t index) {
ImGui::PopID(); ImGui::PopID();
} }
ImGui::EndTable(); ImGui::EndTable();
ImGui::SeparatorText("Spoiler Log Rewards"); ImGui::SeparatorText("Spoiler Log Rewards");
ImGui::BeginTable("Item Button Table", 8); ImGui::BeginTable("Item Button Table", 8);
@ -746,7 +735,8 @@ void PlandomizerDrawItemPopup(uint32_t index) {
PlandomizerItemImageCorrection(drawSlots.first); PlandomizerItemImageCorrection(drawSlots.first);
auto name = drawSlots.first.GetName().GetForCurrentLanguage(MF_RAW); auto name = drawSlots.first.GetName().GetForCurrentLanguage(MF_RAW);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(imagePadding, imagePadding)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(imagePadding, imagePadding));
auto ret = ImGui::ImageButton(name.c_str(), textureID, imageSize, textureUV0, textureUV1, ImVec4(0, 0, 0, 0), itemColor); auto ret = ImGui::ImageButton(name.c_str(), textureID, imageSize, textureUV0, textureUV1,
ImVec4(0, 0, 0, 0), itemColor);
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (ret) { if (ret) {
if (itemToDraw.GetRandomizerGet() >= RG_PROGRESSIVE_HOOKSHOT && if (itemToDraw.GetRandomizerGet() >= RG_PROGRESSIVE_HOOKSHOT &&
@ -795,7 +785,8 @@ void PlandomizerDrawIceTrapPopUp(uint32_t index) {
auto name = Rando::StaticData::RetrieveItem(items.first).GetName().GetForCurrentLanguage(MF_RAW); auto name = Rando::StaticData::RetrieveItem(items.first).GetName().GetForCurrentLanguage(MF_RAW);
PlandomizerItemImageCorrection(Rando::StaticData::RetrieveItem(items.first)); PlandomizerItemImageCorrection(Rando::StaticData::RetrieveItem(items.first));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(imagePadding, imagePadding)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(imagePadding, imagePadding));
auto ret = ImGui::ImageButton(name.c_str(), textureID, imageSize, textureUV0, textureUV1, ImVec4(0, 0, 0, 0), itemColor); auto ret = ImGui::ImageButton(name.c_str(), textureID, imageSize, textureUV0, textureUV1,
ImVec4(0, 0, 0, 0), itemColor);
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (ret) { if (ret) {
plandoLogData[index].iceTrapModel = Rando::StaticData::RetrieveItem(items.first); plandoLogData[index].iceTrapModel = Rando::StaticData::RetrieveItem(items.first);
@ -820,7 +811,8 @@ void PlandomizerDrawItemSlots(uint32_t index) {
PlandomizerItemImageCorrection(plandoLogData[index].checkRewardItem); PlandomizerItemImageCorrection(plandoLogData[index].checkRewardItem);
auto name = plandoLogData[index].checkRewardItem.GetName().GetForCurrentLanguage(MF_RAW); auto name = plandoLogData[index].checkRewardItem.GetName().GetForCurrentLanguage(MF_RAW);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(imagePadding, imagePadding)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(imagePadding, imagePadding));
auto ret = ImGui::ImageButton(name.c_str(), textureID, imageSize, textureUV0, textureUV1, ImVec4(0, 0, 0, 0), itemColor); auto ret =
ImGui::ImageButton(name.c_str(), textureID, imageSize, textureUV0, textureUV1, ImVec4(0, 0, 0, 0), itemColor);
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (ret) { if (ret) {
shouldPopup = true; shouldPopup = true;
@ -836,9 +828,15 @@ void PlandomizerDrawItemSlots(uint32_t index) {
void PlandomizerDrawShopSlider(uint32_t index) { void PlandomizerDrawShopSlider(uint32_t index) {
ImGui::PushID(index); ImGui::PushID(index);
UIWidgets::SliderInt("Price:", &plandoLogData[index].shopPrice, UIWidgets::IntSliderOptions() UIWidgets::SliderInt("Price:", &plandoLogData[index].shopPrice,
.Color(THEME_COLOR).Format("%d Rupees").Min(0).Max(999).LabelPosition(UIWidgets::LabelPositions::Near) UIWidgets::IntSliderOptions()
.ComponentAlignment(UIWidgets::ComponentAlignments::Right).Size(UIWidgets::Sizes::Inline)); .Color(THEME_COLOR)
.Format("%d Rupees")
.Min(0)
.Max(999)
.LabelPosition(UIWidgets::LabelPositions::Near)
.ComponentAlignment(UIWidgets::ComponentAlignments::Right)
.Size(UIWidgets::Sizes::Inline));
ImGui::PopID(); ImGui::PopID();
} }
@ -856,7 +854,8 @@ void PlandomizerDrawIceTrapSetup(uint32_t index) {
PlandoPushImageButtonStyle(); PlandoPushImageButtonStyle();
auto name = plandoLogData[index].iceTrapModel.GetName().GetForCurrentLanguage(MF_RAW); auto name = plandoLogData[index].iceTrapModel.GetName().GetForCurrentLanguage(MF_RAW);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(imagePadding, imagePadding)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(imagePadding, imagePadding));
auto ret = ImGui::ImageButton(name.c_str(), textureID, imageSize, textureUV0, textureUV1, ImVec4(0, 0, 0, 0), itemColor); auto ret =
ImGui::ImageButton(name.c_str(), textureID, imageSize, textureUV0, textureUV1, ImVec4(0, 0, 0, 0), itemColor);
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (ret) { if (ret) {
shouldTrapPopup = true; shouldTrapPopup = true;
@ -871,13 +870,19 @@ void PlandomizerDrawIceTrapSetup(uint32_t index) {
ImGui::SameLine(); ImGui::SameLine();
if (plandoLogData[index].iceTrapModel.GetRandomizerGet() != RG_NONE && if (plandoLogData[index].iceTrapModel.GetRandomizerGet() != RG_NONE &&
plandoLogData[index].iceTrapModel.GetRandomizerGet() != RG_SOLD_OUT) { plandoLogData[index].iceTrapModel.GetRandomizerGet() != RG_SOLD_OUT) {
if (UIWidgets::Button(randomizeButton.c_str(), UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline).Padding(ImVec2(10.f, 6.f)))) { if (UIWidgets::Button(randomizeButton.c_str(), UIWidgets::ButtonOptions()
plandoLogData[index].iceTrapName = .Color(THEME_COLOR)
GetIceTrapName(plandoLogData[index].iceTrapModel.GetRandomizerGet()).GetForLanguage(CVarGetInteger(CVAR_SETTING("Languages"), 0)).c_str(); .Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.f, 6.f)))) {
plandoLogData[index].iceTrapName = GetIceTrapName(plandoLogData[index].iceTrapModel.GetRandomizerGet())
.GetForLanguage(CVarGetInteger(CVAR_SETTING("Languages"), 0))
.c_str();
} }
ImGui::SameLine(); ImGui::SameLine();
} }
if (UIWidgets::InputString("##TrapName", &trapTextInput, UIWidgets::InputOptions().Color(THEME_COLOR).LabelPosition(UIWidgets::LabelPositions::None))) { if (UIWidgets::InputString(
"##TrapName", &trapTextInput,
UIWidgets::InputOptions().Color(THEME_COLOR).LabelPosition(UIWidgets::LabelPositions::None))) {
plandoLogData[index].iceTrapName = trapTextInput.c_str(); plandoLogData[index].iceTrapName = trapTextInput.c_str();
} }
@ -932,9 +937,10 @@ void PlandomizerDrawOptions() {
PlandomizerPopulateSeedList(); PlandomizerPopulateSeedList();
static size_t selectedList = 0; static size_t selectedList = 0;
if (existingSeedList.size() != 0) { if (existingSeedList.size() != 0) {
UIWidgets::Combobox("##JsonFiles", &selectedList, existingSeedList, UIWidgets::ComboboxOptions().Color(THEME_COLOR).LabelPosition(UIWidgets::LabelPositions::None)); UIWidgets::Combobox(
} "##JsonFiles", &selectedList, existingSeedList,
else { UIWidgets::ComboboxOptions().Color(THEME_COLOR).LabelPosition(UIWidgets::LabelPositions::None));
} else {
ImGui::Text("No Spoiler Logs found."); ImGui::Text("No Spoiler Logs found.");
} }
ImGui::BeginDisabled(existingSeedList.empty()); ImGui::BeginDisabled(existingSeedList.empty());
@ -964,29 +970,32 @@ void PlandomizerDrawOptions() {
PlandoPushImageButtonStyle(); PlandoPushImageButtonStyle();
for (auto& hash : plandoHash) { for (auto& hash : plandoHash) {
ImGui::PushID(index); ImGui::PushID(index);
textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(gSeedTextures[hash].tex); textureID =
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(gSeedTextures[hash].tex);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 2.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 2.0f));
auto upRet = ImGui::ImageButton("HASH_ARROW_UP", Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("HASH_ARROW_UP"), auto upRet = ImGui::ImageButton(
"HASH_ARROW_UP",
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("HASH_ARROW_UP"),
ImVec2(35.0f, 18.0f), ImVec2(1, 1), ImVec2(0, 0), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)); ImVec2(35.0f, 18.0f), ImVec2(1, 1), ImVec2(0, 0), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1));
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (upRet) { if (upRet) {
if (hash + 1 >= gSeedTextures.size()) { if (hash + 1 >= gSeedTextures.size()) {
hash = 0; hash = 0;
} } else {
else {
hash++; hash++;
} }
} }
ImGui::Image(textureID, ImVec2(35.0f, 35.0f)); ImGui::Image(textureID, ImVec2(35.0f, 35.0f));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 2.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 2.0f));
auto downRet = ImGui::ImageButton("HASH_ARROW_DWN", Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("HASH_ARROW_DWN"), auto downRet = ImGui::ImageButton(
"HASH_ARROW_DWN",
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("HASH_ARROW_DWN"),
ImVec2(35.0f, 18.0f), ImVec2(0, 0), ImVec2(1, 1), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)); ImVec2(35.0f, 18.0f), ImVec2(0, 0), ImVec2(1, 1), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1));
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (downRet) { if (downRet) {
if (hash == 0) { if (hash == 0) {
hash = gSeedTextures.size() - 1; hash = gSeedTextures.size() - 1;
} } else {
else {
hash--; hash--;
} }
} }
@ -999,8 +1008,7 @@ void PlandomizerDrawOptions() {
PlandoPopImageButtonStyle(); PlandoPopImageButtonStyle();
ImGui::EndTable(); ImGui::EndTable();
} }
} } else {
else {
ImGui::Text("No Spoiler Log Loaded"); ImGui::Text("No Spoiler Log Loaded");
} }
ImGui::EndTable(); ImGui::EndTable();
@ -1013,19 +1021,28 @@ void PlandomizerDrawOptions() {
} }
if (getTabID == TAB_HINTS) { if (getTabID == TAB_HINTS) {
if (UIWidgets::Button("Clear All Hints", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) { if (UIWidgets::Button("Clear All Hints",
UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
PlandomizerRemoveAllHints(); PlandomizerRemoveAllHints();
} }
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Randomize All Hints", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) { if (UIWidgets::Button("Randomize All Hints",
UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline))) {
PlandomizerRandomizeHint(HINT_ALL, 0); PlandomizerRandomizeHint(HINT_ALL, 0);
} }
} }
if (getTabID == TAB_LOCATIONS) { if (getTabID == TAB_LOCATIONS) {
if (plandoLogData.size() > 0) { if (plandoLogData.size() > 0) {
UIWidgets::Combobox("Filter by Area:##AreaFilter", &selectedArea, rcAreaNameMap, UIWidgets::ComboboxOptions().Color(THEME_COLOR).LabelPosition(UIWidgets::LabelPositions::Near).ComponentAlignment(UIWidgets::ComponentAlignments::Right)); UIWidgets::Combobox("Filter by Area:##AreaFilter", &selectedArea, rcAreaNameMap,
UIWidgets::ComboboxOptions()
.Color(THEME_COLOR)
.LabelPosition(UIWidgets::LabelPositions::Near)
.ComponentAlignment(UIWidgets::ComponentAlignments::Right));
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Empty All Rewards", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(UIWidgets::Sizes::Inline).Padding(ImVec2(10.f, 6.f)))) { if (UIWidgets::Button("Empty All Rewards", UIWidgets::ButtonOptions()
.Color(THEME_COLOR)
.Size(UIWidgets::Sizes::Inline)
.Padding(ImVec2(10.f, 6.f)))) {
PlandomizerRemoveAllItems(); PlandomizerRemoveAllItems();
} }
} }
@ -1055,12 +1072,20 @@ void PlandomizerDrawHintsWindow() {
} }
ImGui::Text("New Hint: "); ImGui::Text("New Hint: ");
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button(randomizeButton.c_str(), UIWidgets::ButtonOptions().Color(THEME_COLOR).Padding(ImVec2(10.f, 6.f)).Size(UIWidgets::Sizes::Inline).Tooltip("Randomize Hint"))) { if (UIWidgets::Button(randomizeButton.c_str(), UIWidgets::ButtonOptions()
.Color(THEME_COLOR)
.Padding(ImVec2(10.f, 6.f))
.Size(UIWidgets::Sizes::Inline)
.Tooltip("Randomize Hint"))) {
PlandomizerRandomizeHint(HINT_SINGLE, index); PlandomizerRandomizeHint(HINT_SINGLE, index);
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 10); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 10);
if (UIWidgets::InputString("##HintMessage", &hintInputText, UIWidgets::InputOptions().Color(THEME_COLOR).LabelPosition(UIWidgets::LabelPositions::None).Tooltip(plandomizerHintsTooltip().c_str()))) { if (UIWidgets::InputString("##HintMessage", &hintInputText,
UIWidgets::InputOptions()
.Color(THEME_COLOR)
.LabelPosition(UIWidgets::LabelPositions::None)
.Tooltip(plandomizerHintsTooltip().c_str()))) {
plandoHintData[index].hintText = hintInputText.c_str(); plandoHintData[index].hintText = hintInputText.c_str();
} }
index++; index++;
@ -1078,7 +1103,8 @@ void PlandomizerDrawLocationsWindow(RandomizerCheckArea rcArea) {
if (ImGui::BeginTable("Locations Window", 4, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY)) { if (ImGui::BeginTable("Locations Window", 4, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY)) {
ImGui::TableSetupColumn("Spoiler Log Check Name", ImGuiTableColumnFlags_WidthFixed, 250.0f); ImGui::TableSetupColumn("Spoiler Log Check Name", ImGuiTableColumnFlags_WidthFixed, 250.0f);
ImGui::TableSetupColumn("Spoiler Log Reward", ImGuiTableColumnFlags_WidthFixed, 190.0f); ImGui::TableSetupColumn("Spoiler Log Reward", ImGuiTableColumnFlags_WidthFixed, 190.0f);
ImGui::TableSetupColumn("New Reward", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHeaderLabel, 34.0f); ImGui::TableSetupColumn("New Reward", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHeaderLabel,
34.0f);
ImGui::TableSetupColumn("Additional Options"); ImGui::TableSetupColumn("Additional Options");
ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
@ -1096,8 +1122,7 @@ void PlandomizerDrawLocationsWindow(RandomizerCheckArea rcArea) {
if (plandoLogData[index].checkRewardItem.GetRandomizerGet() == RG_ICE_TRAP) { if (plandoLogData[index].checkRewardItem.GetRandomizerGet() == RG_ICE_TRAP) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
PlandomizerDrawIceTrapSetup(index); PlandomizerDrawIceTrapSetup(index);
} } else if (spoilerData.shopPrice != -1) {
else if (spoilerData.shopPrice != -1) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::BeginTable("Shops", 1, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInner); ImGui::BeginTable("Shops", 1, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInner);
ImGui::TableSetupColumn("Shop Price"); ImGui::TableSetupColumn("Shop Price");
@ -1105,8 +1130,7 @@ void PlandomizerDrawLocationsWindow(RandomizerCheckArea rcArea) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
PlandomizerDrawShopSlider(index); PlandomizerDrawShopSlider(index);
ImGui::EndTable(); ImGui::EndTable();
} } else {
else {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
} }
} }
@ -1144,15 +1168,25 @@ void PlandomizerWindow::DrawElement() {
} }
void PlandomizerWindow::InitElement() { void PlandomizerWindow::InitElement() {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_RUPEE_GRAYSCALE", gRupeeCounterIconTex, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_RUPEE_GRAYSCALE", gRupeeCounterIconTex,
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_HEART_GRAYSCALE", gHeartFullTex, ImVec4(0.87f, 0.10f, 0.10f, 1)); ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_SEEDS", gItemIconDekuSeedsTex, ImVec4( 1, 1, 1, 1 )); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_HEART_GRAYSCALE", gHeartFullTex,
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ARROWS_SMALL", gDropArrows1Tex, ImVec4( 1, 1, 1, 1 )); ImVec4(0.87f, 0.10f, 0.10f, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ARROWS_MEDIUM", gDropArrows2Tex, ImVec4( 1, 1, 1, 1 )); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_SEEDS", gItemIconDekuSeedsTex,
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ARROWS_LARGE", gDropArrows3Tex, ImVec4( 1, 1, 1, 1 )); ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ICE_TRAP", gMagicArrowEquipEffectTex, ImVec4( 1, 1, 1, 1 )); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ARROWS_SMALL", gDropArrows1Tex,
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("HASH_ARROW_UP", gEmptyCDownArrowTex, ImVec4( 1, 1, 1, 1 )); ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("HASH_ARROW_DWN", gEmptyCDownArrowTex, ImVec4( 1, 1, 1, 1 )); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ARROWS_MEDIUM", gDropArrows2Tex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ARROWS_LARGE", gDropArrows3Tex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ICE_TRAP", gMagicArrowEquipEffectTex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("HASH_ARROW_UP", gEmptyCDownArrowTex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("HASH_ARROW_DWN", gEmptyCDownArrowTex,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("BOSS_SOUL", gBossSoulTex, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("BOSS_SOUL", gBossSoulTex, ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("TRIFORCE_PIECE", gTriforcePieceTex, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("TRIFORCE_PIECE", gTriforcePieceTex,
ImVec4(1, 1, 1, 1));
} }

View file

@ -38,7 +38,8 @@ void RegisterShuffleCows() {
COND_VB_SHOULD(VB_GIVE_ITEM_FROM_COW, shouldRegister, { COND_VB_SHOULD(VB_GIVE_ITEM_FROM_COW, shouldRegister, {
EnCow* enCow = va_arg(args, EnCow*); EnCow* enCow = va_arg(args, EnCow*);
CowIdentity cowIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCow(gPlayState->sceneNum, enCow->actor.world.pos.x, enCow->actor.world.pos.z); CowIdentity cowIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCow(
gPlayState->sceneNum, enCow->actor.world.pos.x, enCow->actor.world.pos.z);
// Has this cow already rewarded an item? // Has this cow already rewarded an item?
if (!Flags_GetRandomizerInf(cowIdentity.randomizerInf)) { if (!Flags_GetRandomizerInf(cowIdentity.randomizerInf)) {
Flags_SetRandomizerInf(cowIdentity.randomizerInf); Flags_SetRandomizerInf(cowIdentity.randomizerInf);
@ -60,7 +61,8 @@ static RegisterShipInitFunc initFunc(RegisterShuffleCows, { "IS_RANDO" });
void Rando::StaticData::RegisterCowLocations() { void Rando::StaticData::RegisterCowLocations() {
static bool registered = false; static bool registered = false;
if (registered) return; if (registered)
return;
registered = true; registered = true;
// clang-format off // clang-format off
locationTable[RC_KF_LINKS_HOUSE_COW] = Location::Base(RC_KF_LINKS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, ACTOR_EN_COW, SCENE_LINKS_HOUSE, 0x00, "Links House Cow", RHT_KF_LINKS_HOUSE_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW)); locationTable[RC_KF_LINKS_HOUSE_COW] = Location::Base(RC_KF_LINKS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, ACTOR_EN_COW, SCENE_LINKS_HOUSE, 0x00, "Links House Cow", RHT_KF_LINKS_HOUSE_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW));

View file

@ -25,7 +25,8 @@ extern "C" void ObjKibako2_RandomizerDraw(Actor* thisx, PlayState* play) {
int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED); int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED);
int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0); int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0);
int isVanilla = csmc == CSMC_DISABLED || csmc == CSMC_SIZE || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)); int isVanilla =
csmc == CSMC_DISABLED || csmc == CSMC_SIZE || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY));
if (isVanilla) { if (isVanilla) {
Gfx_DrawDListOpa(play, (Gfx*)gLargeRandoCrateDL); Gfx_DrawDListOpa(play, (Gfx*)gLargeRandoCrateDL);
@ -44,8 +45,10 @@ extern "C" void ObjKibako2_RandomizerDraw(Actor* thisx, PlayState* play) {
crateItem.getItemId == GI_BOMBCHUS_20)))) { crateItem.getItemId == GI_BOMBCHUS_20)))) {
getItemCategory = ITEM_CATEGORY_JUNK; getItemCategory = ITEM_CATEGORY_JUNK;
// If it's a bottle and they already have one, consider the item lesser // If it's a bottle and they already have one, consider the item lesser
} else if ((crateItem.modIndex == MOD_RANDOMIZER && crateItem.getItemId >= RG_BOTTLE_WITH_RED_POTION && crateItem.getItemId <= RG_BOTTLE_WITH_POE) || } else if ((crateItem.modIndex == MOD_RANDOMIZER && crateItem.getItemId >= RG_BOTTLE_WITH_RED_POTION &&
(crateItem.modIndex == MOD_NONE && (crateItem.getItemId == GI_BOTTLE || crateItem.getItemId == GI_MILK_BOTTLE))) { crateItem.getItemId <= RG_BOTTLE_WITH_POE) ||
(crateItem.modIndex == MOD_NONE &&
(crateItem.getItemId == GI_BOTTLE || crateItem.getItemId == GI_MILK_BOTTLE))) {
if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) { if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) {
getItemCategory = ITEM_CATEGORY_LESSER; getItemCategory = ITEM_CATEGORY_LESSER;
} }
@ -90,26 +93,30 @@ extern "C" void ObjKibako_RandomizerDraw(Actor* thisx, PlayState* play) {
int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED); int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED);
int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0); int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0);
int isVanilla = csmc == CSMC_DISABLED || csmc == CSMC_SIZE || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)); int isVanilla =
csmc == CSMC_DISABLED || csmc == CSMC_SIZE || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY));
if (isVanilla) { if (isVanilla) {
Gfx_DrawDListOpa(play, (Gfx*)gSmallRandoCrateDL); Gfx_DrawDListOpa(play, (Gfx*)gSmallRandoCrateDL);
return; return;
} }
GetItemEntry smallCrateItem = Rando::Context::GetInstance()->GetFinalGIEntry(smallCrateActor->smallCrateIdentity.randomizerCheck, true, GI_NONE); GetItemEntry smallCrateItem = Rando::Context::GetInstance()->GetFinalGIEntry(
smallCrateActor->smallCrateIdentity.randomizerCheck, true, GI_NONE);
getItemCategory = smallCrateItem.getItemCategory; getItemCategory = smallCrateItem.getItemCategory;
// If they have bombchus, don't consider the bombchu item major // If they have bombchus, don't consider the bombchu item major
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU && if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU &&
((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId == RG_PROGRESSIVE_BOMBCHUS) || ((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId == RG_PROGRESSIVE_BOMBCHUS) ||
(smallCrateItem.modIndex == MOD_NONE && (smallCrateItem.modIndex == MOD_NONE &&
(smallCrateItem.getItemId == GI_BOMBCHUS_5 || smallCrateItem.getItemId == GI_BOMBCHUS_10 || smallCrateItem.getItemId == GI_BOMBCHUS_20)))) { (smallCrateItem.getItemId == GI_BOMBCHUS_5 || smallCrateItem.getItemId == GI_BOMBCHUS_10 ||
smallCrateItem.getItemId == GI_BOMBCHUS_20)))) {
getItemCategory = ITEM_CATEGORY_JUNK; getItemCategory = ITEM_CATEGORY_JUNK;
// If it's a bottle and they already have one, consider the item lesser // If it's a bottle and they already have one, consider the item lesser
} else if ((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId >= RG_BOTTLE_WITH_RED_POTION && } else if ((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId >= RG_BOTTLE_WITH_RED_POTION &&
smallCrateItem.getItemId <= RG_BOTTLE_WITH_POE) || smallCrateItem.getItemId <= RG_BOTTLE_WITH_POE) ||
(smallCrateItem.modIndex == MOD_NONE && (smallCrateItem.getItemId == GI_BOTTLE || smallCrateItem.getItemId == GI_MILK_BOTTLE))) { (smallCrateItem.modIndex == MOD_NONE &&
(smallCrateItem.getItemId == GI_BOTTLE || smallCrateItem.getItemId == GI_MILK_BOTTLE))) {
if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) { if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) {
getItemCategory = ITEM_CATEGORY_LESSER; getItemCategory = ITEM_CATEGORY_LESSER;
} }
@ -183,7 +190,8 @@ uint8_t ObjKibako_RandomizerHoldsItem(ObjKibako* smallCrateActor, PlayState* pla
void ObjKibako2_RandomizerSpawnCollectible(ObjKibako2* crateActor, PlayState* play) { void ObjKibako2_RandomizerSpawnCollectible(ObjKibako2* crateActor, PlayState* play) {
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &crateActor->dyna.actor.world.pos, ITEM00_SOH_DUMMY); EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &crateActor->dyna.actor.world.pos, ITEM00_SOH_DUMMY);
item00->randoInf = crateActor->crateIdentity.randomizerInf; item00->randoInf = crateActor->crateIdentity.randomizerInf;
item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(crateActor->crateIdentity.randomizerCheck, true, GI_NONE); item00->itemEntry =
Rando::Context::GetInstance()->GetFinalGIEntry(crateActor->crateIdentity.randomizerCheck, true, GI_NONE);
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f; item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f; item00->actor.speedXZ = 2.0f;
@ -193,8 +201,8 @@ void ObjKibako2_RandomizerSpawnCollectible(ObjKibako2* crateActor, PlayState* pl
void ObjKibako_RandomizerSpawnCollectible(ObjKibako* smallCrateActor, PlayState* play) { void ObjKibako_RandomizerSpawnCollectible(ObjKibako* smallCrateActor, PlayState* play) {
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &smallCrateActor->actor.world.pos, ITEM00_SOH_DUMMY); EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &smallCrateActor->actor.world.pos, ITEM00_SOH_DUMMY);
item00->randoInf = smallCrateActor->smallCrateIdentity.randomizerInf; item00->randoInf = smallCrateActor->smallCrateIdentity.randomizerInf;
item00->itemEntry = item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(
Rando::Context::GetInstance()->GetFinalGIEntry(smallCrateActor->smallCrateIdentity.randomizerCheck, true, GI_NONE); smallCrateActor->smallCrateIdentity.randomizerCheck, true, GI_NONE);
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f; item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f; item00->actor.speedXZ = 2.0f;
@ -207,29 +215,38 @@ void ObjKibako2_RandomizerInit(void* actorRef) {
// don't shuffle two OOB crates in GF and don't shuffle child GV/GF crates when not in no logic // don't shuffle two OOB crates in GF and don't shuffle child GV/GF crates when not in no logic
if (actor->id != ACTOR_OBJ_KIBAKO2 || if (actor->id != ACTOR_OBJ_KIBAKO2 ||
(gPlayState->sceneNum == SCENE_GERUDOS_FORTRESS && (s16)actor->world.pos.x == -4051 && (s16)actor->world.pos.z == -3429) || (gPlayState->sceneNum == SCENE_GERUDOS_FORTRESS && (s16)actor->world.pos.x == -4051 &&
(gPlayState->sceneNum == SCENE_GERUDOS_FORTRESS && (s16)actor->world.pos.x == -4571 && (s16)actor->world.pos.z == -3429) || (s16)actor->world.pos.z == -3429) ||
(logicSetting != RO_LOGIC_NO_LOGIC && (gPlayState->sceneNum == SCENE_GERUDOS_FORTRESS && (s16)actor->world.pos.x == -4571 &&
((gPlayState->sceneNum == SCENE_GERUDOS_FORTRESS && (s16)actor->world.pos.x == 3443 && (s16)actor->world.pos.z == -4876) || (s16)actor->world.pos.z == -3429) ||
(gPlayState->sceneNum == SCENE_GERUDO_VALLEY && (s16)actor->world.pos.x == -764 && (s16)actor->world.pos.z == 148) || (logicSetting != RO_LOGIC_NO_LOGIC && ((gPlayState->sceneNum == SCENE_GERUDOS_FORTRESS &&
(gPlayState->sceneNum == SCENE_GERUDO_VALLEY && (s16)actor->world.pos.x == -860 && (s16)actor->world.pos.z == -125) || (s16)actor->world.pos.x == 3443 && (s16)actor->world.pos.z == -4876) ||
(gPlayState->sceneNum == SCENE_GERUDO_VALLEY && (s16)actor->world.pos.x == -860 && (s16)actor->world.pos.z == -150) || (gPlayState->sceneNum == SCENE_GERUDO_VALLEY &&
(gPlayState->sceneNum == SCENE_GERUDO_VALLEY && (s16)actor->world.pos.x == -860 && (s16)actor->world.pos.z == -90)))) (s16)actor->world.pos.x == -764 && (s16)actor->world.pos.z == 148) ||
(gPlayState->sceneNum == SCENE_GERUDO_VALLEY &&
(s16)actor->world.pos.x == -860 && (s16)actor->world.pos.z == -125) ||
(gPlayState->sceneNum == SCENE_GERUDO_VALLEY &&
(s16)actor->world.pos.x == -860 && (s16)actor->world.pos.z == -150) ||
(gPlayState->sceneNum == SCENE_GERUDO_VALLEY &&
(s16)actor->world.pos.x == -860 && (s16)actor->world.pos.z == -90))))
return; return;
ObjKibako2* crateActor = static_cast<ObjKibako2*>(actorRef); ObjKibako2* crateActor = static_cast<ObjKibako2*>(actorRef);
crateActor->crateIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCrate(gPlayState->sceneNum, (s16)actor->world.pos.x, (s16)actor->world.pos.z); crateActor->crateIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCrate(
gPlayState->sceneNum, (s16)actor->world.pos.x, (s16)actor->world.pos.z);
} }
void ObjKibako_RandomizerInit(void* actorRef) { void ObjKibako_RandomizerInit(void* actorRef) {
Actor* actor = static_cast<Actor*>(actorRef); Actor* actor = static_cast<Actor*>(actorRef);
if (actor->id != ACTOR_OBJ_KIBAKO) return; if (actor->id != ACTOR_OBJ_KIBAKO)
return;
ObjKibako* smallCrateActor = static_cast<ObjKibako*>(actorRef); ObjKibako* smallCrateActor = static_cast<ObjKibako*>(actorRef);
smallCrateActor->smallCrateIdentity = OTRGlobals::Instance->gRandomizer->IdentifySmallCrate(gPlayState->sceneNum, (s16)actor->home.pos.x, (s16)actor->home.pos.z); smallCrateActor->smallCrateIdentity = OTRGlobals::Instance->gRandomizer->IdentifySmallCrate(
gPlayState->sceneNum, (s16)actor->home.pos.x, (s16)actor->home.pos.z);
} }
void RegisterShuffleCrates() { void RegisterShuffleCrates() {
@ -274,12 +291,12 @@ void RegisterShuffleCrates() {
*should = true; *should = true;
} }
}); });
} }
void Rando::StaticData::RegisterCrateLocations() { void Rando::StaticData::RegisterCrateLocations() {
static bool registered = false; static bool registered = false;
if (registered) return; if (registered)
return;
registered = true; registered = true;
// clang-format off // clang-format off
// Overworld Crates // Overworld Crates

View file

@ -52,14 +52,16 @@ FairyIdentity ShuffleFairies_GetFairyIdentity(int32_t params) {
sceneNum = SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY; sceneNum = SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY;
} }
Rando::Location* location = OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(ACTOR_EN_ELF, sceneNum, params); Rando::Location* location =
OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(ACTOR_EN_ELF, sceneNum, params);
if (location->GetRandomizerCheck() == RC_UNKNOWN_CHECK) { if (location->GetRandomizerCheck() == RC_UNKNOWN_CHECK) {
LUSLOG_WARN("FairyGetIdentity did not receive a valid RC value (%d).", location->GetRandomizerCheck()); LUSLOG_WARN("FairyGetIdentity did not receive a valid RC value (%d).", location->GetRandomizerCheck());
assert(false); assert(false);
} else { } else {
fairyIdentity.randomizerInf = static_cast<RandomizerInf>(location->GetCollectionCheck().flag); fairyIdentity.randomizerInf = static_cast<RandomizerInf>(location->GetCollectionCheck().flag);
fairyIdentity.itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(location->GetRandomizerCheck(), true, GI_FAIRY); fairyIdentity.itemEntry =
Rando::Context::GetInstance()->GetFinalGIEntry(location->GetRandomizerCheck(), true, GI_FAIRY);
} }
return fairyIdentity; return fairyIdentity;
@ -97,8 +99,7 @@ void ShuffleFairies_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should,
s16 grottoId = (gPlayState->sceneNum == SCENE_FAIRYS_FOUNTAIN) ? Grotto_CurrentGrotto() : 0; s16 grottoId = (gPlayState->sceneNum == SCENE_FAIRYS_FOUNTAIN) ? Grotto_CurrentGrotto() : 0;
for (s16 index = 0; index < 8; index++) { for (s16 index = 0; index < 8; index++) {
int32_t params = (grottoId << 8) | index; int32_t params = (grottoId << 8) | index;
if (ShuffleFairies_SpawnFairy(actor->world.pos.x, actor->world.pos.y, actor->world.pos.z, if (ShuffleFairies_SpawnFairy(actor->world.pos.x, actor->world.pos.y, actor->world.pos.z, params)) {
params)) {
fairySpawned = true; fairySpawned = true;
} }
} }
@ -112,8 +113,7 @@ void ShuffleFairies_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should,
for (s16 index = 0; index < 3; index++) { for (s16 index = 0; index < 3; index++) {
int32_t params = ((objBean->dyna.actor.params & 0x3F) << 8) | index; int32_t params = ((objBean->dyna.actor.params & 0x3F) << 8) | index;
if (ShuffleFairies_SpawnFairy(objBean->dyna.actor.world.pos.x, objBean->dyna.actor.world.pos.y, if (ShuffleFairies_SpawnFairy(objBean->dyna.actor.world.pos.x, objBean->dyna.actor.world.pos.y,
objBean->dyna.actor.world.pos.z, objBean->dyna.actor.world.pos.z, params)) {
params)) {
fairySpawned = true; fairySpawned = true;
} }
} }
@ -136,10 +136,8 @@ void ShuffleFairies_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should,
// Otherwise fall back to vanilla behaviour. // Otherwise fall back to vanilla behaviour.
if (gPlayState->msgCtx.ocarinaMode == OCARINA_MODE_04 && if (gPlayState->msgCtx.ocarinaMode == OCARINA_MODE_04 &&
(gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_LULLABY || (gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_LULLABY ||
gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_SARIAS || gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_SARIAS || gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_EPONAS ||
gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_EPONAS || gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_SUNS || gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_TIME ||
gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_SUNS ||
gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_TIME ||
gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_STORMS)) { gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_STORMS)) {
int32_t params = (gPlayState->sceneNum == SCENE_GROTTOS) ? Grotto_CurrentGrotto() : 0; int32_t params = (gPlayState->sceneNum == SCENE_GROTTOS) ? Grotto_CurrentGrotto() : 0;
@ -175,7 +173,8 @@ void ShuffleFairies_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should,
uint32_t onVanillaBehaviorHook = 0; uint32_t onVanillaBehaviorHook = 0;
void ShuffleFairies_RegisterHooks() { void ShuffleFairies_RegisterHooks() {
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(ShuffleFairies_OnVanillaBehaviorHandler); onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(
ShuffleFairies_OnVanillaBehaviorHandler);
} }
void ShuffleFairies_UnregisterHooks() { void ShuffleFairies_UnregisterHooks() {
@ -186,7 +185,8 @@ void ShuffleFairies_UnregisterHooks() {
void Rando::StaticData::RegisterFairyLocations() { void Rando::StaticData::RegisterFairyLocations() {
static bool registered = false; static bool registered = false;
if (registered) return; if (registered)
return;
registered = true; registered = true;
// clang-format off // clang-format off
locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_1] = Location::Fairy(RC_SFM_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1800, "Grotto Fairy 1", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_1)); locationTable[RC_SFM_FAIRY_GROTTO_FAIRY_1] = Location::Fairy(RC_SFM_FAIRY_GROTTO_FAIRY_1, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_FAIRYS_FOUNTAIN, 0x1800, "Grotto Fairy 1", RHT_SFM_FAIRY_GROTTO_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_1));

View file

@ -20,17 +20,17 @@ void ShuffleFreestanding_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* sh
} }
uint32_t params = TWO_ACTOR_PARAMS((int32_t)item00->actor.world.pos.x, (int32_t)item00->actor.world.pos.z); uint32_t params = TWO_ACTOR_PARAMS((int32_t)item00->actor.world.pos.x, (int32_t)item00->actor.world.pos.z);
Rando::Location* loc = OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(item00->actor.id, gPlayState->sceneNum, params); Rando::Location* loc =
OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(item00->actor.id, gPlayState->sceneNum, params);
uint8_t isDungeon = loc->IsDungeon(); uint8_t isDungeon = loc->IsDungeon();
uint8_t freestandingSetting = uint8_t freestandingSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_FREESTANDING).Get();
Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_FREESTANDING).Get();
RandomizerCheck randomizerCheck = loc->GetRandomizerCheck(); RandomizerCheck randomizerCheck = loc->GetRandomizerCheck();
bool checkObtained = Rando::Context::GetInstance()->GetItemLocation(randomizerCheck)->HasObtained(); bool checkObtained = Rando::Context::GetInstance()->GetItemLocation(randomizerCheck)->HasObtained();
// Don't change to randomized item if current freestanding item isn't shuffled or already obtained. // Don't change to randomized item if current freestanding item isn't shuffled or already obtained.
if ((freestandingSetting == RO_SHUFFLE_FREESTANDING_OVERWORLD && isDungeon) || if ((freestandingSetting == RO_SHUFFLE_FREESTANDING_OVERWORLD && isDungeon) ||
(freestandingSetting == RO_SHUFFLE_FREESTANDING_DUNGEONS && !isDungeon) || (freestandingSetting == RO_SHUFFLE_FREESTANDING_DUNGEONS && !isDungeon) || checkObtained ||
checkObtained || randomizerCheck == RC_UNKNOWN_CHECK) { randomizerCheck == RC_UNKNOWN_CHECK) {
return; return;
} }
@ -46,7 +46,8 @@ void ShuffleFreestanding_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* sh
void Rando::StaticData::RegisterFreestandingLocations() { void Rando::StaticData::RegisterFreestandingLocations() {
static bool registered = false; static bool registered = false;
if (registered) return; if (registered)
return;
registered = true; registered = true;
// clang-format off // clang-format off
locationTable[RC_KF_BOULDER_RUPEE_2] = Location::Collectable(RC_KF_BOULDER_RUPEE_2, RCQUEST_BOTH, RCTYPE_FREESTANDING, ACTOR_EN_ITEM00, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS(-712, 1857), "Boulder Maze Second Rupee", RHT_KOKIRI_FOREST_RUPEE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BOULDER_RUPEE_2)); locationTable[RC_KF_BOULDER_RUPEE_2] = Location::Collectable(RC_KF_BOULDER_RUPEE_2, RCQUEST_BOTH, RCTYPE_FREESTANDING, ACTOR_EN_ITEM00, SCENE_KOKIRI_FOREST, TWO_ACTOR_PARAMS(-712, 1857), "Boulder Maze Second Rupee", RHT_KOKIRI_FOREST_RUPEE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BOULDER_RUPEE_2));

View file

@ -32,11 +32,13 @@ extern "C" void EnKusa_RandomizerDraw(Actor* thisx, PlayState* play) {
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx); Gfx_SetupDL_25Opa(play->state.gfxCtx);
if (grassActor->grassIdentity.randomizerCheck != RC_MAX && Flags_GetRandomizerInf(grassActor->grassIdentity.randomizerInf) == 0) { if (grassActor->grassIdentity.randomizerCheck != RC_MAX &&
Flags_GetRandomizerInf(grassActor->grassIdentity.randomizerInf) == 0) {
int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED); int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED);
if (csmc == CSMC_BOTH || csmc == CSMC_TEXTURE) { if (csmc == CSMC_BOTH || csmc == CSMC_TEXTURE) {
auto itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(grassActor->grassIdentity.randomizerCheck, true, GI_NONE); auto itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(grassActor->grassIdentity.randomizerCheck,
true, GI_NONE);
GetItemCategory getItemCategory = itemEntry.getItemCategory; GetItemCategory getItemCategory = itemEntry.getItemCategory;
switch (getItemCategory) { switch (getItemCategory) {
@ -48,10 +50,12 @@ extern "C" void EnKusa_RandomizerDraw(Actor* thisx, PlayState* play) {
case ITEM_HEART_PIECE: case ITEM_HEART_PIECE:
case ITEM_HEART_PIECE_2: case ITEM_HEART_PIECE_2:
case ITEM_HEART_CONTAINER: case ITEM_HEART_CONTAINER:
DrawTypeOfGrass(grassActor, (Gfx*)gRandoBushHeartDL, (Gfx*)gRandoCuttableGrassHeartDL, play); DrawTypeOfGrass(grassActor, (Gfx*)gRandoBushHeartDL, (Gfx*)gRandoCuttableGrassHeartDL,
play);
break; break;
default: default:
DrawTypeOfGrass(grassActor, (Gfx*)gRandoBushMinorDL, (Gfx*)gRandoCuttableGrassMinorDL, play); DrawTypeOfGrass(grassActor, (Gfx*)gRandoBushMinorDL, (Gfx*)gRandoCuttableGrassMinorDL,
play);
break; break;
} }
break; break;
@ -155,10 +159,10 @@ void RegisterShuffleGrass() {
}); });
} }
void Rando::StaticData::RegisterGrassLocations() { void Rando::StaticData::RegisterGrassLocations() {
static bool registered = false; static bool registered = false;
if (registered) return; if (registered)
return;
registered = true; registered = true;
// clang-format off // clang-format off
// Overworld Grass // Overworld Grass

View file

@ -11,7 +11,6 @@ extern PlayState* gPlayState;
extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play); extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) { extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) {
float potSize = 1.0f; float potSize = 1.0f;
@ -44,7 +43,8 @@ uint8_t ObjTsubo_RandomizerHoldsItem(ObjTsubo* potActor, PlayState* play) {
void ObjTsubo_RandomizerSpawnCollectible(ObjTsubo* potActor, PlayState* play) { void ObjTsubo_RandomizerSpawnCollectible(ObjTsubo* potActor, PlayState* play) {
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &potActor->actor.world.pos, ITEM00_SOH_DUMMY); EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &potActor->actor.world.pos, ITEM00_SOH_DUMMY);
item00->randoInf = potActor->potIdentity.randomizerInf; item00->randoInf = potActor->potIdentity.randomizerInf;
item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(potActor->potIdentity.randomizerCheck, true, GI_NONE); item00->itemEntry =
Rando::Context::GetInstance()->GetFinalGIEntry(potActor->potIdentity.randomizerCheck, true, GI_NONE);
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f; item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f; item00->actor.speedXZ = 2.0f;
@ -56,7 +56,8 @@ void ObjTsubo_RandomizerInit(void* actorRef) {
ObjTsubo* potActor = static_cast<ObjTsubo*>(actorRef); ObjTsubo* potActor = static_cast<ObjTsubo*>(actorRef);
potActor->potIdentity = OTRGlobals::Instance->gRandomizer->IdentifyPot(gPlayState->sceneNum, (s16)actor->world.pos.x, (s16)actor->world.pos.z); potActor->potIdentity = OTRGlobals::Instance->gRandomizer->IdentifyPot(
gPlayState->sceneNum, (s16)actor->world.pos.x, (s16)actor->world.pos.z);
} }
void ShufflePots_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs) { void ShufflePots_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs) {
@ -96,7 +97,8 @@ void ShufflePots_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va
void Rando::StaticData::RegisterPotLocations() { void Rando::StaticData::RegisterPotLocations() {
static bool registered = false; static bool registered = false;
if (registered) return; if (registered)
return;
registered = true; registered = true;
// clang-format off // clang-format off
// Overworld Pots // Overworld Pots

View file

@ -118,12 +118,14 @@ ItemOverride& Context::GetItemOverride(size_t locKey) {
return overrides.at(static_cast<RandomizerCheck>(locKey)); return overrides.at(static_cast<RandomizerCheck>(locKey));
} }
void Context::PlaceItemInLocation(const RandomizerCheck locKey, const RandomizerGet item, const bool applyEffectImmediately, void Context::PlaceItemInLocation(const RandomizerCheck locKey, const RandomizerGet item,
const bool setHidden) { const bool applyEffectImmediately, const bool setHidden) {
const auto loc = GetItemLocation(locKey); const auto loc = GetItemLocation(locKey);
SPDLOG_DEBUG(StaticData::RetrieveItem(item).GetName().GetForCurrentLanguage(MF_RAW) + " placed at " + StaticData::GetLocation(locKey)->GetName() + "\n"); SPDLOG_DEBUG(StaticData::RetrieveItem(item).GetName().GetForCurrentLanguage(MF_RAW) + " placed at " +
StaticData::GetLocation(locKey)->GetName() + "\n");
if (applyEffectImmediately || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_GLITCHLESS) || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_VANILLA)) { if (applyEffectImmediately || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_GLITCHLESS) ||
mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_VANILLA)) {
StaticData::RetrieveItem(item).ApplyEffect(); StaticData::RetrieveItem(item).ApplyEffect();
} }
@ -164,26 +166,29 @@ void Context::GenerateLocationPool() {
// TODO: Exclude checks for some of the older shuffles from the pool too i.e. Frog Songs, Scrubs, etc.) // TODO: Exclude checks for some of the older shuffles from the pool too i.e. Frog Songs, Scrubs, etc.)
if (location.GetRandomizerCheck() == RC_UNKNOWN_CHECK || if (location.GetRandomizerCheck() == RC_UNKNOWN_CHECK ||
location.GetRandomizerCheck() == RC_TRIFORCE_COMPLETED || // already in pool location.GetRandomizerCheck() == RC_TRIFORCE_COMPLETED || // already in pool
(location.GetRandomizerCheck() == RC_MASTER_SWORD_PEDESTAL && mOptions[RSK_SHUFFLE_MASTER_SWORD].Is(RO_GENERIC_OFF)) || (location.GetRandomizerCheck() == RC_MASTER_SWORD_PEDESTAL &&
(location.GetRandomizerCheck() == RC_KAK_100_GOLD_SKULLTULA_REWARD && mOptions[RSK_SHUFFLE_100_GS_REWARD].Is(RO_GENERIC_OFF)) || mOptions[RSK_SHUFFLE_MASTER_SWORD].Is(RO_GENERIC_OFF)) ||
(location.GetRandomizerCheck() == RC_KAK_100_GOLD_SKULLTULA_REWARD &&
mOptions[RSK_SHUFFLE_100_GS_REWARD].Is(RO_GENERIC_OFF)) ||
location.GetRCType() == RCTYPE_CHEST_GAME || // not supported yet location.GetRCType() == RCTYPE_CHEST_GAME || // not supported yet
location.GetRCType() == RCTYPE_STATIC_HINT || // can't have items location.GetRCType() == RCTYPE_STATIC_HINT || // can't have items
location.GetRCType() == RCTYPE_GOSSIP_STONE || // can't have items location.GetRCType() == RCTYPE_GOSSIP_STONE || // can't have items
(location.GetRCType() == RCTYPE_FROG_SONG && mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES].Is(RO_GENERIC_OFF)) || (location.GetRCType() == RCTYPE_FROG_SONG && mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES].Is(RO_GENERIC_OFF)) ||
(location.GetRCType() == RCTYPE_SCRUB && mOptions[RSK_SHUFFLE_SCRUBS].Is(RO_SCRUBS_OFF)) || (location.GetRCType() == RCTYPE_SCRUB && mOptions[RSK_SHUFFLE_SCRUBS].Is(RO_SCRUBS_OFF)) ||
(location.GetRCType() == RCTYPE_SCRUB && mOptions[RSK_SHUFFLE_SCRUBS].Is(RO_SCRUBS_ONE_TIME_ONLY) && !( (location.GetRCType() == RCTYPE_SCRUB && mOptions[RSK_SHUFFLE_SCRUBS].Is(RO_SCRUBS_ONE_TIME_ONLY) &&
location.GetRandomizerCheck() == RC_LW_DEKU_SCRUB_GROTTO_FRONT || !(location.GetRandomizerCheck() == RC_LW_DEKU_SCRUB_GROTTO_FRONT ||
location.GetRandomizerCheck() == RC_LW_DEKU_SCRUB_NEAR_BRIDGE || location.GetRandomizerCheck() == RC_LW_DEKU_SCRUB_NEAR_BRIDGE ||
location.GetRandomizerCheck() == RC_HF_DEKU_SCRUB_GROTTO location.GetRandomizerCheck() == RC_HF_DEKU_SCRUB_GROTTO)) ||
)) ||
(location.GetRCType() == RCTYPE_ADULT_TRADE && mOptions[RSK_SHUFFLE_ADULT_TRADE].Is(RO_GENERIC_OFF)) || (location.GetRCType() == RCTYPE_ADULT_TRADE && mOptions[RSK_SHUFFLE_ADULT_TRADE].Is(RO_GENERIC_OFF)) ||
(location.GetRCType() == RCTYPE_COW && mOptions[RSK_SHUFFLE_COWS].Is(RO_GENERIC_OFF)) || (location.GetRCType() == RCTYPE_COW && mOptions[RSK_SHUFFLE_COWS].Is(RO_GENERIC_OFF)) ||
(location.GetRandomizerCheck() == RC_LH_HYRULE_LOACH && mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_HYRULE_LOACH)) || (location.GetRandomizerCheck() == RC_LH_HYRULE_LOACH &&
mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_HYRULE_LOACH)) ||
(location.GetRCType() == RCTYPE_FISH && !mFishsanity->GetFishLocationIncluded(&location)) || (location.GetRCType() == RCTYPE_FISH && !mFishsanity->GetFishLocationIncluded(&location)) ||
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OFF)) || (location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OFF)) ||
(location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_OFF)) || (location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_OFF)) ||
(location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF)) || (location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF)) ||
(location.GetRCType() == RCTYPE_NLCRATE && (mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF) || !mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC))) || (location.GetRCType() == RCTYPE_NLCRATE && (mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF) ||
!mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC))) ||
(location.GetRCType() == RCTYPE_SMALL_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF)) || (location.GetRCType() == RCTYPE_SMALL_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF)) ||
(location.GetRCType() == RCTYPE_FAIRY && !mOptions[RSK_SHUFFLE_FAIRIES]) || (location.GetRCType() == RCTYPE_FAIRY && !mOptions[RSK_SHUFFLE_FAIRIES]) ||
(location.GetRCType() == RCTYPE_FREESTANDING && (location.GetRCType() == RCTYPE_FREESTANDING &&
@ -194,13 +199,17 @@ void Context::GenerateLocationPool() {
if (location.IsOverworld()) { if (location.IsOverworld()) {
// Skip stuff that is shuffled to dungeon only, i.e. tokens, pots, etc., or other checks that // Skip stuff that is shuffled to dungeon only, i.e. tokens, pots, etc., or other checks that
// should not have a shuffled item. // should not have a shuffled item.
if ((location.GetRCType() == RCTYPE_FREESTANDING && mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_DUNGEONS)) || if ((location.GetRCType() == RCTYPE_FREESTANDING &&
mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_DUNGEONS)) ||
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_DUNGEONS)) || (location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_DUNGEONS)) ||
(location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_DUNGEONS)) || (location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_DUNGEONS)) ||
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_DUNGEONS)) || (location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_DUNGEONS)) ||
(location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS)) || (location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS)) ||
(location.GetRCType() == RCTYPE_NLCRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS) && mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC)) || (location.GetRCType() == RCTYPE_NLCRATE &&
(location.GetRCType() == RCTYPE_SMALL_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS))) { mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS) &&
mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC)) ||
(location.GetRCType() == RCTYPE_SMALL_CRATE &&
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS))) {
continue; continue;
} }
// If we've gotten past all the conditions where an overworld location should not be // If we've gotten past all the conditions where an overworld location should not be
@ -213,10 +222,15 @@ void Context::GenerateLocationPool() {
if ((location.GetRCType() == RCTYPE_FREESTANDING && if ((location.GetRCType() == RCTYPE_FREESTANDING &&
mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_OVERWORLD)) || mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_OVERWORLD)) ||
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OVERWORLD)) || (location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OVERWORLD)) ||
(location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_OVERWORLD)) || (location.GetRCType() == RCTYPE_GRASS &&
(location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD)) || mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_OVERWORLD)) ||
(location.GetRCType() == RCTYPE_NLCRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD) && mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC)) || (location.GetRCType() == RCTYPE_CRATE &&
(location.GetRCType() == RCTYPE_SMALL_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD))) { mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD)) ||
(location.GetRCType() == RCTYPE_NLCRATE &&
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD) &&
mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC)) ||
(location.GetRCType() == RCTYPE_SMALL_CRATE &&
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD))) {
continue; continue;
} }
// also add to that dungeon's location list. // also add to that dungeon's location list.
@ -230,15 +244,14 @@ void Context::GenerateLocationPool() {
void Context::AddExcludedOptions() { void Context::AddExcludedOptions() {
for (auto& loc : StaticData::GetLocationTable()) { for (auto& loc : StaticData::GetLocationTable()) {
// Checks of these types don't have items, skip them. // Checks of these types don't have items, skip them.
if (loc.GetRandomizerCheck() == RC_UNKNOWN_CHECK || if (loc.GetRandomizerCheck() == RC_UNKNOWN_CHECK || loc.GetRandomizerCheck() == RC_TRIFORCE_COMPLETED ||
loc.GetRandomizerCheck() == RC_TRIFORCE_COMPLETED || loc.GetRCType() == RCTYPE_CHEST_GAME || loc.GetRCType() == RCTYPE_CHEST_GAME || loc.GetRCType() == RCTYPE_STATIC_HINT ||
loc.GetRCType() == RCTYPE_STATIC_HINT || loc.GetRCType() == RCTYPE_GOSSIP_STONE) { loc.GetRCType() == RCTYPE_GOSSIP_STONE) {
continue; continue;
} }
AddLocation(loc.GetRandomizerCheck(), &everyPossibleLocation); AddLocation(loc.GetRandomizerCheck(), &everyPossibleLocation);
bool alreadyAdded = false; bool alreadyAdded = false;
for (Option* location : Rando::Settings::GetInstance()->GetExcludeOptionsForArea(loc.GetArea())) for (Option* location : Rando::Settings::GetInstance()->GetExcludeOptionsForArea(loc.GetArea())) {
{
if (location->GetName() == loc.GetExcludedOption()->GetName()) { if (location->GetName() == loc.GetExcludedOption()->GetName()) {
alreadyAdded = true; alreadyAdded = true;
} }
@ -249,7 +262,8 @@ void Context::AddExcludedOptions() {
} }
} }
std::vector<RandomizerCheck> Context::GetLocations(const std::vector<RandomizerCheck>& locationPool, const RandomizerCheckType checkType) { std::vector<RandomizerCheck> Context::GetLocations(const std::vector<RandomizerCheck>& locationPool,
const RandomizerCheckType checkType) {
std::vector<RandomizerCheck> locationsOfType; std::vector<RandomizerCheck> locationsOfType;
for (RandomizerCheck locKey : locationPool) { for (RandomizerCheck locKey : locationPool) {
if (StaticData::GetLocation(locKey)->GetRCType() == checkType) { if (StaticData::GetLocation(locKey)->GetRCType() == checkType) {
@ -331,7 +345,8 @@ void Context::SetSpoilerLoaded(const bool spoilerLoaded) {
mSpoilerLoaded = spoilerLoaded; mSpoilerLoaded = spoilerLoaded;
} }
GetItemEntry Context::GetFinalGIEntry(const RandomizerCheck rc, const bool checkObtainability, const GetItemID ogItemId) { GetItemEntry Context::GetFinalGIEntry(const RandomizerCheck rc, const bool checkObtainability,
const GetItemID ogItemId) {
const auto itemLoc = GetItemLocation(rc); const auto itemLoc = GetItemLocation(rc);
if (itemLoc->GetPlacedRandomizerGet() == RG_NONE) { if (itemLoc->GetPlacedRandomizerGet() == RG_NONE) {
if (ogItemId != GI_NONE) { if (ogItemId != GI_NONE) {
@ -392,9 +407,7 @@ void Context::ParseSpoiler(const char* spoilerFileName) {
mTrials->ParseJson(spoilerFileJson); mTrials->ParseJson(spoilerFileJson);
mSpoilerLoaded = true; mSpoilerLoaded = true;
mSeedGenerated = false; mSeedGenerated = false;
} catch (...) { } catch (...) { LUSLOG_ERROR("Failed to load Spoiler File: %s", spoilerFileName); }
LUSLOG_ERROR("Failed to load Spoiler File: %s", spoilerFileName);
}
} }
void Context::ParseHashIconIndexesJson(nlohmann::json spoilerFileJson) { void Context::ParseHashIconIndexesJson(nlohmann::json spoilerFileJson) {

View file

@ -53,7 +53,8 @@ class Context {
void AddLocations(const Container& locations, std::vector<RandomizerCheck>* destination = nullptr); void AddLocations(const Container& locations, std::vector<RandomizerCheck>* destination = nullptr);
bool IsQuestOfLocationActive(RandomizerCheck rc); bool IsQuestOfLocationActive(RandomizerCheck rc);
void GenerateLocationPool(); void GenerateLocationPool();
static std::vector<RandomizerCheck> GetLocations(const std::vector<RandomizerCheck>& locationPool, const RandomizerCheckType checkType); static std::vector<RandomizerCheck> GetLocations(const std::vector<RandomizerCheck>& locationPool,
const RandomizerCheckType checkType);
void AddExcludedOptions(); void AddExcludedOptions();
void LocationReset(); void LocationReset();
void ClearItemLocations(); void ClearItemLocations();

View file

@ -40,29 +40,19 @@ extern SaveContext gSaveContext;
} }
const char* SmallBodyCvarValue[10] = { const char* SmallBodyCvarValue[10] = {
CVAR_COSMETIC("Key.ForestSmallBody.Value"), CVAR_COSMETIC("Key.ForestSmallBody.Value"), CVAR_COSMETIC("Key.FireSmallBody.Value"),
CVAR_COSMETIC("Key.FireSmallBody.Value"), CVAR_COSMETIC("Key.WaterSmallBody.Value"), CVAR_COSMETIC("Key.SpiritSmallBody.Value"),
CVAR_COSMETIC("Key.WaterSmallBody.Value"), CVAR_COSMETIC("Key.ShadowSmallBody.Value"), CVAR_COSMETIC("Key.WellSmallBody.Value"),
CVAR_COSMETIC("Key.SpiritSmallBody.Value"), CVAR_COSMETIC("Key.GTGSmallBody.Value"), CVAR_COSMETIC("Key.FortSmallBody.Value"),
CVAR_COSMETIC("Key.ShadowSmallBody.Value"), CVAR_COSMETIC("Key.GanonsSmallBody.Value"), CVAR_COSMETIC("Key.ChestGameSmallBody.Value"),
CVAR_COSMETIC("Key.WellSmallBody.Value"),
CVAR_COSMETIC("Key.GTGSmallBody.Value"),
CVAR_COSMETIC("Key.FortSmallBody.Value"),
CVAR_COSMETIC("Key.GanonsSmallBody.Value"),
CVAR_COSMETIC("Key.ChestGameSmallBody.Value"),
}; };
const char* SmallEmblemCvarValue[10] = { const char* SmallEmblemCvarValue[10] = {
CVAR_COSMETIC("Key.ForestSmallEmblem.Value"), CVAR_COSMETIC("Key.ForestSmallEmblem.Value"), CVAR_COSMETIC("Key.FireSmallEmblem.Value"),
CVAR_COSMETIC("Key.FireSmallEmblem.Value"), CVAR_COSMETIC("Key.WaterSmallEmblem.Value"), CVAR_COSMETIC("Key.SpiritSmallEmblem.Value"),
CVAR_COSMETIC("Key.WaterSmallEmblem.Value"), CVAR_COSMETIC("Key.ShadowSmallEmblem.Value"), CVAR_COSMETIC("Key.WellSmallEmblem.Value"),
CVAR_COSMETIC("Key.SpiritSmallEmblem.Value"), CVAR_COSMETIC("Key.GTGSmallEmblem.Value"), CVAR_COSMETIC("Key.FortSmallEmblem.Value"),
CVAR_COSMETIC("Key.ShadowSmallEmblem.Value"), CVAR_COSMETIC("Key.GanonsSmallEmblem.Value"), CVAR_COSMETIC("Key.ChestGameEmblem.Value"),
CVAR_COSMETIC("Key.WellSmallEmblem.Value"),
CVAR_COSMETIC("Key.GTGSmallEmblem.Value"),
CVAR_COSMETIC("Key.FortSmallEmblem.Value"),
CVAR_COSMETIC("Key.GanonsSmallEmblem.Value"),
CVAR_COSMETIC("Key.ChestGameEmblem.Value"),
}; };
Color_RGB8 SmallEmblemDefaultValue[10] = { Color_RGB8 SmallEmblemDefaultValue[10] = {
@ -85,16 +75,11 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn
int slot = getItemEntry->drawItemId - RG_FOREST_TEMPLE_SMALL_KEY; int slot = getItemEntry->drawItemId - RG_FOREST_TEMPLE_SMALL_KEY;
Gfx* customIconDLs[] = { Gfx* customIconDLs[] = {
(Gfx*)gSmallKeyIconForestTempleDL, (Gfx*)gSmallKeyIconForestTempleDL, (Gfx*)gSmallKeyIconFireTempleDL,
(Gfx*)gSmallKeyIconFireTempleDL, (Gfx*)gSmallKeyIconWaterTempleDL, (Gfx*)gSmallKeyIconSpiritTempleDL,
(Gfx*)gSmallKeyIconWaterTempleDL, (Gfx*)gSmallKeyIconShadowTempleDL, (Gfx*)gSmallKeyIconBottomoftheWellDL,
(Gfx*)gSmallKeyIconSpiritTempleDL, (Gfx*)gSmallKeyIconGerudoTrainingGroundDL, (Gfx*)gSmallKeyIconGerudoFortressDL,
(Gfx*)gSmallKeyIconShadowTempleDL, (Gfx*)gSmallKeyIconGanonsCastleDL, (Gfx*)gSmallKeyIconTreasureChestGameDL,
(Gfx*)gSmallKeyIconBottomoftheWellDL,
(Gfx*)gSmallKeyIconGerudoTrainingGroundDL,
(Gfx*)gSmallKeyIconGerudoFortressDL,
(Gfx*)gSmallKeyIconGanonsCastleDL,
(Gfx*)gSmallKeyIconTreasureChestGameDL,
}; };
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
@ -150,7 +135,8 @@ extern "C" void Randomizer_DrawMap(PlayState* play, GetItemEntry* getItemEntry)
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx); Gfx_SetupDL_25Opa(play->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
@ -179,15 +165,18 @@ extern "C" void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEnt
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx); Gfx_SetupDL_25Opa(play->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
gDPSetEnvColor(POLY_OPA_DISP++, colors[color_slot][0] / 2, colors[color_slot][1] / 2, colors[color_slot][2] / 2, 255); gDPSetEnvColor(POLY_OPA_DISP++, colors[color_slot][0] / 2, colors[color_slot][1] / 2, colors[color_slot][2] / 2,
255);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiCompassDL); gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiCompassDL);
POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 5); POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 5);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiCompassGlassDL); gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiCompassGlassDL);
CLOSE_DISPS(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);
@ -198,21 +187,13 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt
s16 slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_BOSS_KEY; s16 slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_BOSS_KEY;
std::string CvarValue[6] = { std::string CvarValue[6] = {
"gCosmetics.Key.ForestBoss", "gCosmetics.Key.ForestBoss", "gCosmetics.Key.FireBoss", "gCosmetics.Key.WaterBoss",
"gCosmetics.Key.FireBoss", "gCosmetics.Key.SpiritBoss", "gCosmetics.Key.ShadowBoss", "gCosmetics.Key.GanonsBoss",
"gCosmetics.Key.WaterBoss",
"gCosmetics.Key.SpiritBoss",
"gCosmetics.Key.ShadowBoss",
"gCosmetics.Key.GanonsBoss",
}; };
Gfx* CustomdLists[] = { Gfx* CustomdLists[] = {
(Gfx*)gBossKeyIconForestTempleDL, (Gfx*)gBossKeyIconForestTempleDL, (Gfx*)gBossKeyIconFireTempleDL, (Gfx*)gBossKeyIconWaterTempleDL,
(Gfx*)gBossKeyIconFireTempleDL, (Gfx*)gBossKeyIconSpiritTempleDL, (Gfx*)gBossKeyIconShadowTempleDL, (Gfx*)gBossKeyIconGanonsCastleDL,
(Gfx*)gBossKeyIconWaterTempleDL,
(Gfx*)gBossKeyIconSpiritTempleDL,
(Gfx*)gBossKeyIconShadowTempleDL,
(Gfx*)gBossKeyIconGanonsCastleDL,
}; };
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
@ -270,54 +251,35 @@ extern "C" void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEnt
int slot = getItemEntry->drawItemId - RG_FOREST_TEMPLE_KEY_RING; int slot = getItemEntry->drawItemId - RG_FOREST_TEMPLE_KEY_RING;
Gfx* CustomIconDLs[] = { Gfx* CustomIconDLs[] = {
(Gfx*)gKeyringIconForestTempleDL, (Gfx*)gKeyringIconForestTempleDL, (Gfx*)gKeyringIconFireTempleDL,
(Gfx*)gKeyringIconFireTempleDL, (Gfx*)gKeyringIconWaterTempleDL, (Gfx*)gKeyringIconSpiritTempleDL,
(Gfx*)gKeyringIconWaterTempleDL, (Gfx*)gKeyringIconShadowTempleDL, (Gfx*)gKeyringIconBottomoftheWellDL,
(Gfx*)gKeyringIconSpiritTempleDL, (Gfx*)gKeyringIconGerudoTrainingGroundDL, (Gfx*)gKeyringIconGerudoFortressDL,
(Gfx*)gKeyringIconShadowTempleDL, (Gfx*)gKeyringIconGanonsCastleDL, (Gfx*)gKeyringIconTreasureChestGameDL,
(Gfx*)gKeyringIconBottomoftheWellDL,
(Gfx*)gKeyringIconGerudoTrainingGroundDL,
(Gfx*)gKeyringIconGerudoFortressDL,
(Gfx*)gKeyringIconGanonsCastleDL,
(Gfx*)gKeyringIconTreasureChestGameDL,
}; };
Gfx* CustomKeysDLs[] = { Gfx* CustomKeysDLs[] = {
(Gfx*)gKeyringKeysForestTempleDL, (Gfx*)gKeyringKeysForestTempleDL, (Gfx*)gKeyringKeysFireTempleDL,
(Gfx*)gKeyringKeysFireTempleDL, (Gfx*)gKeyringKeysWaterTempleDL, (Gfx*)gKeyringKeysSpiritTempleDL,
(Gfx*)gKeyringKeysWaterTempleDL, (Gfx*)gKeyringKeysShadowTempleDL, (Gfx*)gKeyringKeysBottomoftheWellDL,
(Gfx*)gKeyringKeysSpiritTempleDL, (Gfx*)gKeyringKeysGerudoTrainingGroundDL, (Gfx*)gKeyringKeysGerudoFortressDL,
(Gfx*)gKeyringKeysShadowTempleDL, (Gfx*)gKeyringKeysGanonsCastleDL, (Gfx*)gKeyringKeysTreasureChestGameDL,
(Gfx*)gKeyringKeysBottomoftheWellDL,
(Gfx*)gKeyringKeysGerudoTrainingGroundDL,
(Gfx*)gKeyringKeysGerudoFortressDL,
(Gfx*)gKeyringKeysGanonsCastleDL,
(Gfx*)gKeyringKeysTreasureChestGameDL,
}; };
Gfx* CustomKeysMQDLs[] = { Gfx* CustomKeysMQDLs[] = {
(Gfx*)gKeyringKeysForestTempleMQDL, (Gfx*)gKeyringKeysForestTempleMQDL, (Gfx*)gKeyringKeysFireTempleMQDL,
(Gfx*)gKeyringKeysFireTempleMQDL, (Gfx*)gKeyringKeysWaterTempleMQDL, (Gfx*)gKeyringKeysSpiritTempleMQDL,
(Gfx*)gKeyringKeysWaterTempleMQDL, (Gfx*)gKeyringKeysShadowTempleMQDL, (Gfx*)gKeyringKeysBottomoftheWellMQDL,
(Gfx*)gKeyringKeysSpiritTempleMQDL, (Gfx*)gKeyringKeysGerudoTrainingGroundMQDL, (Gfx*)gKeyringKeysGerudoFortressDL,
(Gfx*)gKeyringKeysShadowTempleMQDL, (Gfx*)gKeyringKeysGanonsCastleMQDL, (Gfx*)gKeyringKeysTreasureChestGameDL,
(Gfx*)gKeyringKeysBottomoftheWellMQDL,
(Gfx*)gKeyringKeysGerudoTrainingGroundMQDL,
(Gfx*)gKeyringKeysGerudoFortressDL,
(Gfx*)gKeyringKeysGanonsCastleMQDL,
(Gfx*)gKeyringKeysTreasureChestGameDL,
}; };
//RANDOTODO make DungeonInfo static and vanilla accessible to allow all these key model data vars to be stored there. // RANDOTODO make DungeonInfo static and vanilla accessible to allow all these key model data vars to be stored
//(Rando::DungeonKey)0 means the keyring is not tied to a dungeon and should not be checked for an MQ variant // there. (Rando::DungeonKey)0 means the keyring is not tied to a dungeon and should not be checked for an MQ
// variant
Rando::DungeonKey SlotToDungeon[10] = { Rando::DungeonKey SlotToDungeon[10] = {
Rando::FOREST_TEMPLE, Rando::FOREST_TEMPLE, Rando::FIRE_TEMPLE, Rando::WATER_TEMPLE, Rando::SPIRIT_TEMPLE,
Rando::FIRE_TEMPLE, Rando::SHADOW_TEMPLE, Rando::BOTTOM_OF_THE_WELL, Rando::GERUDO_TRAINING_GROUND,
Rando::WATER_TEMPLE,
Rando::SPIRIT_TEMPLE,
Rando::SHADOW_TEMPLE,
Rando::BOTTOM_OF_THE_WELL,
Rando::GERUDO_TRAINING_GROUND,
(Rando::DungeonKey)0, // Gerudo Fortress (Rando::DungeonKey)0, // Gerudo Fortress
Rando::GANONS_CASTLE, Rando::GANONS_CASTLE,
(Rando::DungeonKey)0, // Treasure Chest Game (Rando::DungeonKey)0, // Treasure Chest Game
@ -388,7 +350,8 @@ extern "C" void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry* getI
Gfx_SetupDL_25Xlu(play->state.gfxCtx); Gfx_SetupDL_25Xlu(play->state.gfxCtx);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gDPSetGrayscaleColor(POLY_XLU_DISP++, 255, 255, 255, 255); gDPSetGrayscaleColor(POLY_XLU_DISP++, 255, 255, 255, 255);
gSPGrayscale(POLY_XLU_DISP++, true); gSPGrayscale(POLY_XLU_DISP++, true);
@ -514,7 +477,8 @@ extern "C" void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry* getIte
Gfx_SetupDL_25Xlu(play->state.gfxCtx); Gfx_SetupDL_25Xlu(play->state.gfxCtx);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gDPSetGrayscaleColor(POLY_XLU_DISP++, color.r, color.g, color.b, 255); gDPSetGrayscaleColor(POLY_XLU_DISP++, color.r, color.g, color.b, 255);
gSPGrayscale(POLY_XLU_DISP++, true); gSPGrayscale(POLY_XLU_DISP++, true);
@ -619,7 +583,8 @@ extern "C" void DrawKingDodongo(PlayState* play) {
CLOSE_DISPS(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);
} }
extern "C" s32 OverrideLimbDrawBarinade(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { extern "C" s32 OverrideLimbDrawBarinade(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
void* thisx) {
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
s16 unk_1AC = play->gameplayFrames * 0xC31; s16 unk_1AC = play->gameplayFrames * 0xC31;
@ -860,7 +825,8 @@ extern "C" void DrawBongoBongo(PlayState* play) {
CLOSE_DISPS(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);
} }
extern "C" s32 OverrideLimbDrawKotake(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { extern "C" s32 OverrideLimbDrawKotake(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
void* thisx) {
if (limbIndex == 21) { // Head if (limbIndex == 21) { // Head
*dList = (Gfx*)gTwinrovaKotakeHeadDL; *dList = (Gfx*)gTwinrovaKotakeHeadDL;
} }
@ -1084,26 +1050,20 @@ extern "C" void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getI
s16 slot = getItemEntry->drawItemId - RG_OCARINA_A_BUTTON; s16 slot = getItemEntry->drawItemId - RG_OCARINA_A_BUTTON;
Gfx* dLists[] = { Gfx* dLists[] = {
(Gfx*)gOcarinaAButtonDL, (Gfx*)gOcarinaAButtonDL, (Gfx*)gOcarinaCUpButtonDL, (Gfx*)gOcarinaCDownButtonDL,
(Gfx*)gOcarinaCUpButtonDL, (Gfx*)gOcarinaCLeftButtonDL, (Gfx*)gOcarinaCRightButtonDL,
(Gfx*)gOcarinaCDownButtonDL,
(Gfx*)gOcarinaCLeftButtonDL,
(Gfx*)gOcarinaCRightButtonDL,
}; };
Color_RGB8 colors[] = { Color_RGB8 colors[] = {
aButtonColor, aButtonColor, cUpButtonColor, cDownButtonColor, cLeftButtonColor, cRightButtonColor,
cUpButtonColor,
cDownButtonColor,
cLeftButtonColor,
cRightButtonColor,
}; };
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Xlu(play->state.gfxCtx); Gfx_SetupDL_25Xlu(play->state.gfxCtx);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gDPSetGrayscaleColor(POLY_XLU_DISP++, colors[slot].r, colors[slot].g, colors[slot].b, 255); gDPSetGrayscaleColor(POLY_XLU_DISP++, colors[slot].r, colors[slot].g, colors[slot].b, 255);
gSPGrayscale(POLY_XLU_DISP++, true); gSPGrayscale(POLY_XLU_DISP++, true);
@ -1139,7 +1099,8 @@ extern "C" void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getIte
-1 * (play->state.frames * 2), 64, 64, 1, 1 * (play->state.frames * 4), -1 * (play->state.frames * 2), 64, 64, 1, 1 * (play->state.frames * 4),
1 * -(play->state.frames * 4), 32, 32)); 1 * -(play->state.frames * 4), 32, 32));
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiBronzeScaleColorDL); gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiBronzeScaleColorDL);
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiScaleDL); gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiScaleDL);
@ -1198,7 +1159,6 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI
CLOSE_DISPS(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);
} }
extern "C" void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry) { extern "C" void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry) {
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);

View file

@ -29,7 +29,10 @@ void Randomizer_DrawBombchuBag(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getItemEntry);
#define GET_ITEM_MYSTERY \ #define GET_ITEM_MYSTERY \
{ ITEM_NONE_FE, 0, 0, 0, 0, MOD_RANDOMIZER, MOD_RANDOMIZER, ITEM_NONE_FE, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, ITEM_NONE_FE, MOD_RANDOMIZER, (CustomDrawFunc)Randomizer_DrawMysteryItem } { \
ITEM_NONE_FE, 0, 0, 0, 0, MOD_RANDOMIZER, MOD_RANDOMIZER, ITEM_NONE_FE, 0, false, ITEM_FROM_NPC, \
ITEM_CATEGORY_JUNK, ITEM_NONE_FE, MOD_RANDOMIZER, (CustomDrawFunc)Randomizer_DrawMysteryItem \
}
#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif #endif

Some files were not shown because too many files have changed in this diff Show more