Merge branch 'develop' of github.com:Malkierian/Shipwright into log-level-selector

This commit is contained in:
Malkierian 2025-04-02 09:11:07 -07:00
commit 125a84653c
891 changed files with 40536 additions and 36316 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

View file

@ -10,6 +10,8 @@ set(CVAR_PREFIX_TRACKER "gTrackers")
set(CVAR_PREFIX_DEVELOPER_TOOLS "gDeveloperTools") set(CVAR_PREFIX_DEVELOPER_TOOLS "gDeveloperTools")
set(CVAR_PREFIX_GENERAL "gGeneral") set(CVAR_PREFIX_GENERAL "gGeneral")
set(CVAR_PREFIX_REMOTE "gRemote") set(CVAR_PREFIX_REMOTE "gRemote")
set(CVAR_PREFIX_GAMEPLAY_STATS "gGameplayStats")
set(CVAR_PREFIX_TIME_DISPLAY "gTimeDisplay")
add_compile_definitions( add_compile_definitions(
CVAR_PREFIX_RANDOMIZER_ENHANCEMENT="${CVAR_PREFIX_RANDOMIZER_ENHANCEMENT}" CVAR_PREFIX_RANDOMIZER_ENHANCEMENT="${CVAR_PREFIX_RANDOMIZER_ENHANCEMENT}"
CVAR_PREFIX_RANDOMIZER_SETTING="${CVAR_PREFIX_RANDOMIZER_SETTING}" CVAR_PREFIX_RANDOMIZER_SETTING="${CVAR_PREFIX_RANDOMIZER_SETTING}"
@ -23,4 +25,6 @@ add_compile_definitions(
CVAR_PREFIX_DEVELOPER_TOOLS="${CVAR_PREFIX_DEVELOPER_TOOLS}" CVAR_PREFIX_DEVELOPER_TOOLS="${CVAR_PREFIX_DEVELOPER_TOOLS}"
CVAR_PREFIX_GENERAL="${CVAR_PREFIX_GENERAL}" CVAR_PREFIX_GENERAL="${CVAR_PREFIX_GENERAL}"
CVAR_PREFIX_REMOTE="${CVAR_PREFIX_REMOTE}" CVAR_PREFIX_REMOTE="${CVAR_PREFIX_REMOTE}"
CVAR_PREFIX_GAMEPLAY_STATS="${CVAR_PREFIX_GAMEPLAY_STATS}"
CVAR_PREFIX_TIME_DISPLAY="${CVAR_PREFIX_TIME_DISPLAY}"
) )

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

@ -1,5 +1,5 @@
#include <unistd.h> #include <unistd.h>
long pathconf(const char *path, int name) { long pathconf(const char* path, int name) {
return -1; return -1;
} }

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

@ -39,7 +39,7 @@ struct ActorDBInit {
}; };
class ActorDB { class ActorDB {
public: public:
static ActorDB* Instance; static ActorDB* Instance;
ActorDB(); ActorDB();
@ -65,7 +65,8 @@ 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

@ -22,7 +22,7 @@ static std::array<const char*, ACTORCAT_MAX> sCatToStrArray{
#define DEFINE_SCENE(_1, _2, enumName, _4, _5, _6) #enumName #define DEFINE_SCENE(_1, _2, enumName, _4, _5, _6) #enumName
static std::array<const char*, SCENE_ID_MAX> sSceneIdToStrArray{ static std::array<const char*, SCENE_ID_MAX> sSceneIdToStrArray{
#include "tables/scene_table.h" #include "tables/scene_table.h"
}; };
#undef DEFINE_SCENE #undef DEFINE_SCENE
@ -46,7 +46,7 @@ static void CrashHandler_WriteActorData(char* buffer, size_t* pos) {
ActorListEntry* entry = &gPlayState->actorCtx.actorLists[i]; ActorListEntry* entry = &gPlayState->actorCtx.actorLists[i];
Actor* cur; Actor* cur;
if(entry->length == 0) { if (entry->length == 0) {
continue; continue;
} }
WRITE_VAR_LINE(buffer, pos, "Actor Cat: ", sCatToStrArray[i]); WRITE_VAR_LINE(buffer, pos, "Actor Cat: ", sCatToStrArray[i]);

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,28 +39,27 @@ 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__)
".", ".",
#else #else
",\nor drop a spoiler log on the game window.", ",\nor drop a spoiler log on the game window.",
#endif #endif
// German // German
"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__)
".", ".",
#else #else
",\nor drop a spoiler log on the game window.", ",\nor drop a spoiler log on the game window.",
#endif #endif
// French // French
"Aucune Seed de Randomizer actuellement disponible.\nGénérez-en une dans les \"Randomizer Settings\"" "Aucune Seed de Randomizer actuellement disponible.\nGénérez-en une dans les \"Randomizer Settings\""
#if (defined(__WIIU__) || defined(__SWITCH__)) #if (defined(__WIIU__) || defined(__SWITCH__))
"." "."
#else #else
"\nou glissez un spoilerlog sur la fenêtre du jeu." "\nou glissez un spoilerlog sur la fenêtre du jeu."
#endif #endif
}, },
}; };

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

@ -10,14 +10,14 @@
std::string FormatLocations(std::vector<RandomizerCheck> locs) { std::string FormatLocations(std::vector<RandomizerCheck> locs) {
std::string locString = ""; std::string locString = "";
for (auto loc: locs) { for (auto loc : locs) {
locString += std::to_string(loc) + ","; locString += std::to_string(loc) + ",";
} }
return locString; return locString;
} }
void applyPreset(std::vector<PresetEntry> entries) { void applyPreset(std::vector<PresetEntry> entries) {
for(auto& [cvar, type, value] : entries) { for (auto& [cvar, type, value] : entries) {
switch (type) { switch (type) {
case PRESET_ENTRY_TYPE_S32: case PRESET_ENTRY_TYPE_S32:
CVarSetInteger(cvar, std::get<int32_t>(value)); CVarSetInteger(cvar, std::get<int32_t>(value));
@ -41,20 +41,21 @@ void DrawPresetSelector(PresetType presetTypeId) {
const std::string presetTypeCvar = CVAR_GENERAL("SelectedPresets.") + std::to_string(presetTypeId); const std::string presetTypeCvar = CVAR_GENERAL("SelectedPresets.") + std::to_string(presetTypeId);
const PresetTypeDefinition presetTypeDef = presetTypes.at(presetTypeId); const PresetTypeDefinition presetTypeDef = presetTypes.at(presetTypeId);
uint16_t selectedPresetId = CVarGetInteger(presetTypeCvar.c_str(), 0); uint16_t selectedPresetId = CVarGetInteger(presetTypeCvar.c_str(), 0);
if(selectedPresetId >= presetTypeDef.presets.size()){ if (selectedPresetId >= presetTypeDef.presets.size()) {
selectedPresetId = 0; selectedPresetId = 0;
} }
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);
} }
ImGui::Text("Presets"); ImGui::Text("Presets");
UIWidgets::PushStyleCombobox(THEME_COLOR); UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##PresetsComboBox", selectedPresetDef.label)) { if (ImGui::BeginCombo("##PresetsComboBox", selectedPresetDef.label)) {
for ( auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter ) { for (auto iter = presetTypeDef.presets.begin(); iter != presetTypeDef.presets.end(); ++iter) {
if (ImGui::Selectable(iter->second.label, iter->first == selectedPresetId)) { if (ImGui::Selectable(iter->second.label, iter->first == selectedPresetId)) {
CVarSetInteger(presetTypeCvar.c_str(), iter->first); CVarSetInteger(presetTypeCvar.c_str(), iter->first);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
@ -68,7 +69,7 @@ void DrawPresetSelector(PresetType presetTypeId) {
UIWidgets::PushStyleButton(THEME_COLOR); UIWidgets::PushStyleButton(THEME_COLOR);
if (ImGui::Button(("Apply Preset##" + presetTypeCvar).c_str())) { if (ImGui::Button(("Apply Preset##" + presetTypeCvar).c_str())) {
for(const char* block : presetTypeDef.blocksToClear) { for (const char* block : presetTypeDef.blocksToClear) {
CVarClearBlock(block); CVarClearBlock(block);
} }
if (selectedPresetId != 0) { if (selectedPresetId != 0) {

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

@ -37,10 +37,10 @@ const static std::vector<std::pair<std::string, const char*>> digitList = {
}; };
const std::vector<TimeObject> timeDisplayList = { const std::vector<TimeObject> timeDisplayList = {
{ DISPLAY_IN_GAME_TIMER, "Display Gameplay Timer", CVAR_ENHANCEMENT("TimeDisplay.Timers.InGameTimer") }, { DISPLAY_IN_GAME_TIMER, "Display Gameplay Timer", CVAR_TIME_DISPLAY("Timers.InGameTimer") },
{ DISPLAY_TIME_OF_DAY, "Display Time of Day", CVAR_ENHANCEMENT("TimeDisplay.Timers.TimeofDay") }, { DISPLAY_TIME_OF_DAY, "Display Time of Day", CVAR_TIME_DISPLAY("Timers.TimeofDay") },
{ DISPLAY_CONDITIONAL_TIMER, "Display Conditional Timer", CVAR_ENHANCEMENT("TimeDisplay.Timers.HotWater") }, { DISPLAY_CONDITIONAL_TIMER, "Display Conditional Timer", CVAR_TIME_DISPLAY("Timers.HotWater") },
{ DISPLAY_NAVI_TIMER, "Display Navi Timer", CVAR_ENHANCEMENT("TimeDisplay.Timers.NaviTimer") } { DISPLAY_NAVI_TIMER, "Display Navi Timer", CVAR_TIME_DISPLAY("Timers.NaviTimer") }
}; };
static std::vector<TimeObject> activeTimers; static std::vector<TimeObject> activeTimers;
@ -147,9 +147,9 @@ void TimeDisplayUpdateDisplayOptions() {
} }
} }
//if (pushBack) { // if (pushBack) {
// activeTimers.push_back(timeDisplayList[timeID]); // activeTimers.push_back(timeDisplayList[timeID]);
//} else { // } else {
// uint32_t index = 0; // uint32_t index = 0;
// for (auto& check : activeTimers) { // for (auto& check : activeTimers) {
// if (check.timeID == timeID) { // if (check.timeID == timeID) {
@ -158,7 +158,7 @@ void TimeDisplayUpdateDisplayOptions() {
// } // }
// index++; // index++;
// } // }
//} // }
} }
void TimeDisplayWindow::Draw() { void TimeDisplayWindow::Draw() {
@ -227,11 +227,11 @@ void TimeDisplayWindow::Draw() {
} }
void TimeDisplayInitSettings() { void TimeDisplayInitSettings() {
fontScale = CVarGetFloat(CVAR_ENHANCEMENT("TimeDisplay.FontScale"), 1.0f); fontScale = CVarGetFloat(CVAR_TIME_DISPLAY("FontScale"), 1.0f);
if (fontScale < 1.0f) { if (fontScale < 1.0f) {
fontScale = 1.0f; fontScale = 1.0f;
} }
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeDisplay.ShowWindowBG"), 0)) { if (CVarGetInteger(CVAR_TIME_DISPLAY("ShowWindowBG"), 0)) {
windowBG = ImVec4(0, 0, 0, 0); windowBG = ImVec4(0, 0, 0, 0);
} else { } else {
windowBG = ImVec4(0, 0, 0, 0.5f); windowBG = ImVec4(0, 0, 0, 0.5f);
@ -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

@ -5,9 +5,9 @@ class TimeDisplayWindow : public Ship::GuiWindow {
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
void InitElement() override; void InitElement() override;
void DrawElement() override {}; void DrawElement() override{};
void Draw() override; void Draw() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };
void TimeDisplayUpdateDisplayOptions(); void TimeDisplayUpdateDisplayOptions();

View file

@ -4,12 +4,12 @@
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
#include "functions.h" #include "functions.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
/** /**
@ -20,29 +20,30 @@ 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;
} }
}); });
REGISTER_VB_SHOULD(VB_PLAY_THROW_ANIMATION, { REGISTER_VB_SHOULD(VB_PLAY_THROW_ANIMATION, {
Player *player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
Actor* interactRangeActor = player->interactRangeActor; Actor* interactRangeActor = player->interactRangeActor;
s32 interactActorId = interactRangeActor->id; s32 interactActorId = interactRangeActor->id;
LinkAnimationHeader* anim = va_arg(args, LinkAnimationHeader*); LinkAnimationHeader* anim = va_arg(args, LinkAnimationHeader*);
// 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

@ -4,17 +4,18 @@
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
#include "functions.h" #include "functions.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
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;
@ -28,7 +29,7 @@ void FasterRupeeAccumulator_Register() {
} }
if (gSaveContext.rupeeAccumulator >= 10 && gSaveContext.rupees + 10 < CUR_CAPACITY(UPG_WALLET)) { if (gSaveContext.rupeeAccumulator >= 10 && gSaveContext.rupees + 10 < CUR_CAPACITY(UPG_WALLET)) {
gSaveContext.rupeeAccumulator-= 10; gSaveContext.rupeeAccumulator -= 10;
gSaveContext.rupees += 10; gSaveContext.rupees += 10;
} }
// Losing rupees // Losing rupees

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

@ -3,18 +3,19 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" #include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
} }
/** /**
* This will skip the Deku Tree intro, and simply open the mouth as you approach it. * This will skip the Deku Tree intro, and simply open the mouth as you approach it.
*/ */
void SkipDekuTreeIntro_Register() { void SkipDekuTreeIntro_Register() {
REGISTER_VB_SHOULD(VB_PLAY_DEKU_TREE_INTRO_CS, { REGISTER_VB_SHOULD(VB_PLAY_DEKU_TREE_INTRO_CS, {
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

@ -3,19 +3,21 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
#include "functions.h" #include "functions.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
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

@ -3,7 +3,7 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h" #include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
} }
/** /**
@ -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

@ -3,9 +3,9 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
#include "functions.h" #include "functions.h"
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
void SkipZeldaFleeingCastle_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) { void SkipZeldaFleeingCastle_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
@ -46,13 +46,11 @@ 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>(
sceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([] (int16_t sceneNum) { (uintptr_t)actorPtr, SkipZeldaFleeingCastle_OnActorUpdate);
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);
itemOcarinaUpdateHook = 0; itemOcarinaUpdateHook = 0;
@ -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

@ -3,12 +3,12 @@
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
#include "functions.h" #include "functions.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
/** /**
@ -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

@ -4,17 +4,17 @@
void TimeSavers_Register(); void TimeSavers_Register();
// SkipCutscene // SkipCutscene
// Story // Story
void SkipBlueWarp_Register(); void SkipBlueWarp_Register();
void SkipDekuTreeIntro_Register(); void SkipDekuTreeIntro_Register();
void SkipLostWoodsBridge_Register(); void SkipLostWoodsBridge_Register();
void SkipToGivingZeldasLetter_Register(); void SkipToGivingZeldasLetter_Register();
void SkipZeldaFleeingCastle_Register(); void SkipZeldaFleeingCastle_Register();
void SkipIntro_Register(); void SkipIntro_Register();
// SkipMiscInteractions // SkipMiscInteractions
void MoveJabuJabuElevator_Register(); void MoveJabuJabuElevator_Register();
void MoveMidoInKokiriForest_Register(); void MoveMidoInKokiriForest_Register();
void SkipChildRutoInteractions_Register(); void SkipChildRutoInteractions_Register();
void FasterHeavyBlockLift_Register(); void FasterHeavyBlockLift_Register();
void FasterRupeeAccumulator_Register(); void FasterRupeeAccumulator_Register();

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
@ -355,10 +359,13 @@ void AudioCollection::AddToCollection(char* otrPath, uint16_t seqNum) {
if (typeString == "fanfare") { if (typeString == "fanfare") {
type = SEQ_FANFARE; type = SEQ_FANFARE;
} }
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);
@ -417,7 +427,7 @@ void AudioCollection::InitializeShufflePool() {
shufflePoolInitialized = true; shufflePoolInitialized = true;
}; };
extern "C" void AudioCollection_AddToCollection(char *otrPath, uint16_t seqNum) { extern "C" void AudioCollection_AddToCollection(char* otrPath, uint16_t seqNum) {
AudioCollection::Instance->AddToCollection(otrPath, seqNum); AudioCollection::Instance->AddToCollection(otrPath, seqNum);
} }

View file

@ -37,7 +37,7 @@ class AudioCollection {
// Sequences/SFX to include in/exclude from shuffle pool // Sequences/SFX to include in/exclude from shuffle pool
struct compareSequenceLabel { struct compareSequenceLabel {
bool operator() (SequenceInfo* a, SequenceInfo* b) const { bool operator()(SequenceInfo* a, SequenceInfo* b) const {
return a->label < b->label; return a->label < b->label;
}; };
}; };
@ -69,7 +69,7 @@ class AudioCollection {
std::string GetCvarLockKey(std::string sfxKey); std::string GetCvarLockKey(std::string sfxKey);
}; };
#else #else
void AudioCollection_AddToCollection(char *otrPath, uint16_t seqNum); void AudioCollection_AddToCollection(char* otrPath, uint16_t seqNum);
const char* AudioCollection_GetSequenceName(uint16_t seqId); const char* AudioCollection_GetSequenceName(uint16_t seqId);
bool AudioCollection_HasSequenceNum(uint16_t seqId); bool AudioCollection_HasSequenceNum(uint16_t seqId);
size_t AudioCollection_SequenceMapSize(); size_t AudioCollection_SequenceMapSize();

View file

@ -17,8 +17,8 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor.h"
extern "C" { extern "C" {
#include "z64save.h" #include "z64save.h"
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
} }
Vec3f pos = { 0.0f, 0.0f, 0.0f }; Vec3f pos = { 0.0f, 0.0f, 0.0f };
@ -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"))) {
@ -609,16 +616,10 @@ void AudioEditor::DrawElement() {
excludeTabOpen = true; excludeTabOpen = true;
} }
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

@ -13,8 +13,8 @@ class AudioEditor : public Ship::GuiWindow {
void DrawElement() override; void DrawElement() override;
void InitElement() override; void InitElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
~AudioEditor() {}; ~AudioEditor(){};
}; };
void AudioEditor_RandomizeAll(); void AudioEditor_RandomizeAll();
@ -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

@ -8,18 +8,18 @@
#include <vector> #include <vector>
extern "C" { extern "C" {
#include "functions.h" #include "functions.h"
#include "macros.h" #include "macros.h"
#include "variables.h" #include "variables.h"
#include "src/overlays/actors/ovl_Boss_Goma/z_boss_goma.h" #include "src/overlays/actors/ovl_Boss_Goma/z_boss_goma.h"
#include "src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h" #include "src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h"
#include "src/overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "src/overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
Gfx* KaleidoScope_QuadTextureIA8(Gfx* gfx, void* texture, s16 width, s16 height, u16 point); Gfx* KaleidoScope_QuadTextureIA8(Gfx* gfx, void* texture, s16 width, s16 height, u16 point);
#include "textures/icon_item_nes_static/icon_item_nes_static.h" #include "textures/icon_item_nes_static/icon_item_nes_static.h"
#include "textures/icon_item_ger_static/icon_item_ger_static.h" #include "textures/icon_item_ger_static/icon_item_ger_static.h"
#include "textures/icon_item_fra_static/icon_item_fra_static.h" #include "textures/icon_item_fra_static/icon_item_fra_static.h"
} }
typedef struct BossRushSetting { typedef struct BossRushSetting {
@ -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

@ -5,12 +5,12 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void BossRush_HandleBlueWarpHeal(PlayState* play); void BossRush_HandleBlueWarpHeal(PlayState* play);
void BossRush_InitSave(); void BossRush_InitSave();
const char* BossRush_GetSettingName(u8 optionIndex, u8 language); const char* BossRush_GetSettingName(u8 optionIndex, u8 language);
const char* BossRush_GetSettingChoiceName(u8 optionIndex, u8 choiceIndex, u8 language); const char* BossRush_GetSettingChoiceName(u8 optionIndex, u8 choiceIndex, u8 language);
u8 BossRush_GetSettingOptionsAmount(u8 optionIndex); u8 BossRush_GetSettingOptionsAmount(u8 optionIndex);
void BossRush_RegisterHooks(); void BossRush_RegisterHooks();
#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif #endif

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

@ -18,13 +18,13 @@ typedef enum {
} StickMode; } StickMode;
class InputViewer : public Ship::GuiWindow { class InputViewer : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
void Draw() override; void Draw() override;
void InitElement() override {}; void InitElement() override{};
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
InputViewer(); InputViewer();
~InputViewer(); ~InputViewer();
@ -34,12 +34,12 @@ public:
}; };
class InputViewerSettingsWindow : public Ship::GuiWindow { class InputViewerSettingsWindow : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
void InitElement() override {}; void InitElement() override{};
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
InputViewerSettingsWindow(); InputViewerSettingsWindow();
~InputViewerSettingsWindow(); ~InputViewerSettingsWindow();

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;
@ -57,7 +59,7 @@ void Mouse_RecenterCursor() {
u32 width = GetWindow()->GetWidth(); u32 width = GetWindow()->GetWidth();
u32 height = GetWindow()->GetHeight(); u32 height = GetWindow()->GetHeight();
if (MOUSE_ENABLED) { if (MOUSE_ENABLED) {
GetWindow()->SetMousePos({(s32) (width/2), (s32) (height/2)}); GetWindow()->SetMousePos({ (s32)(width / 2), (s32)(height / 2) });
} }
} }
@ -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);
@ -142,7 +145,7 @@ void Mouse_RegisterUpdateQuickspinCount() {
} }
void Mouse_RegisterHandleQuickspin() { void Mouse_RegisterHandleQuickspin() {
REGISTER_VB_SHOULD(VB_SHOULD_QUICKSPIN, { Mouse_HandleQuickspin(should, va_arg(args, s8*), va_arg(args, s8*)); } ); REGISTER_VB_SHOULD(VB_SHOULD_QUICKSPIN, { Mouse_HandleQuickspin(should, va_arg(args, s8*), va_arg(args, s8*)); });
} }
static RegisterShipInitFunc initFunc_shieldRecenter(Mouse_RegisterRecenterCursorOnShield, { CVAR_ENABLE_MOUSE_NAME }); static RegisterShipInitFunc initFunc_shieldRecenter(Mouse_RegisterRecenterCursorOnShield, { CVAR_ENABLE_MOUSE_NAME });
@ -150,4 +153,4 @@ static RegisterShipInitFunc initFunc_firstPerson(Mouse_RegisterHandleFirstPerson
static RegisterShipInitFunc initFunc_quickspinCount(Mouse_RegisterUpdateQuickspinCount, { CVAR_ENABLE_MOUSE_NAME }); static RegisterShipInitFunc initFunc_quickspinCount(Mouse_RegisterUpdateQuickspinCount, { CVAR_ENABLE_MOUSE_NAME });
static RegisterShipInitFunc initFunc_quickspin(Mouse_RegisterHandleQuickspin, { CVAR_ENABLE_MOUSE_NAME }); static RegisterShipInitFunc initFunc_quickspin(Mouse_RegisterHandleQuickspin, { CVAR_ENABLE_MOUSE_NAME });
static RegisterShipInitFunc initFunc_shieldMove(Mouse_RegisterHandleShield, { CVAR_ENABLE_MOUSE_NAME }); static RegisterShipInitFunc initFunc_shieldMove(Mouse_RegisterHandleShield, { CVAR_ENABLE_MOUSE_NAME });
} //extern "C" } // extern "C"

View file

@ -18,8 +18,8 @@ void Mouse_HandleShield(f32* sp50, f32* sp54);
bool Mouse_HandleQuickspin(bool* should, s8* iter2, s8* sp3C); bool Mouse_HandleQuickspin(bool* should, s8* iter2, s8* sp3C);
void Mouse_UpdateQuickspinCount(); void Mouse_UpdateQuickspinCount();
#ifdef __cplusplus #ifdef __cplusplus
}; //extern "C" }; // extern "C"
#endif #endif
//MOUSE_H // MOUSE_H
#endif #endif

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,37 +1243,34 @@ 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) {
if (has_header) { if (has_header) {
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
} }
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding(); //This is to adjust Vertical pos of item in a cell to be normlized. ImGui::AlignTextToFramePadding(); // This is to adjust Vertical pos of item in a cell to be normlized.
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
} }
void NextCol() { void NextCol() {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
} }
void NextLine() { void NextLine() {
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
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)) {
@ -1457,7 +1522,7 @@ void SohInputEditorWindow::DrawDeviceToggles(uint8_t portIndex) {
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
auto notIgnored = !connectedDeviceManager->PortIsIgnoringInstanceId(portIndex, instanceId); auto notIgnored = !connectedDeviceManager->PortIsIgnoringInstanceId(portIndex, instanceId);
ImGui::PopItemFlag(); ImGui::PopItemFlag();
if(ImGui::Checkbox(StringHelper::Sprintf("###instanceId_%d", instanceId).c_str(), &notIgnored)) { if (ImGui::Checkbox(StringHelper::Sprintf("###instanceId_%d", instanceId).c_str(), &notIgnored)) {
if (notIgnored) { if (notIgnored) {
connectedDeviceManager->UnignoreInstanceIdForPort(portIndex, instanceId); connectedDeviceManager->UnignoreInstanceIdForPort(portIndex, instanceId);
} else { } else {
@ -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,
@ -32,7 +33,7 @@ typedef enum {
extern "C" { extern "C" {
#endif //__cplusplus #endif //__cplusplus
Color_RGBA8 CosmeticsEditor_GetDefaultValue(const char* id); Color_RGBA8 CosmeticsEditor_GetDefaultValue(const char* id);
#ifdef __cplusplus #ifdef __cplusplus
} }
@ -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);
@ -65,6 +67,6 @@ class CosmeticsEditorWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void ApplyDungeonKeyColors(); void ApplyDungeonKeyColors();
void UpdateElement() override {}; void UpdateElement() override{};
}; };
#endif //__cplusplus #endif //__cplusplus

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;
@ -99,7 +103,7 @@ void RegisterNoMasterSword() {
} }
}); });
COND_HOOK(OnPlayerUpdate, IS_RANDO, []{ COND_HOOK(OnPlayerUpdate, IS_RANDO, [] {
static uint16_t lastItemOnB = gSaveContext.equips.buttonItems[0]; static uint16_t lastItemOnB = gSaveContext.equips.buttonItems[0];
if (lastItemOnB != gSaveContext.equips.buttonItems[0]) { if (lastItemOnB != gSaveContext.equips.buttonItems[0]) {
UpdateNoMSPatch(); UpdateNoMSPatch();

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 = {
@ -77,14 +66,15 @@ static std::map<std::string, int> pixelWidthTable = {
CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, TextBoxType type_, CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, TextBoxType type_,
TextBoxPosition position_) TextBoxPosition position_)
: type(type_), position(position_){ : type(type_), position(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_);
} }
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_;
@ -107,7 +98,7 @@ CustomMessage::CustomMessage(std::string english_, std::vector<std::string> colo
position = position_; position = position_;
} }
CustomMessage::CustomMessage(Text text, TextBoxType type_,TextBoxPosition position_) CustomMessage::CustomMessage(Text text, TextBoxType type_, TextBoxPosition position_)
: type(type_), position(position_) { : type(type_), position(position_) {
messages[LANGUAGE_ENG] = text.GetEnglish(); messages[LANGUAGE_ENG] = text.GetEnglish();
messages[LANGUAGE_GER] = text.GetGerman(); messages[LANGUAGE_GER] = text.GetGerman();
@ -141,7 +132,7 @@ CustomMessage CustomMessage::LoadVanillaMessageTableEntry(uint16_t textId) {
TextBoxPosition position = static_cast<TextBoxPosition>(msgEntry->typePos & 0xF); TextBoxPosition position = static_cast<TextBoxPosition>(msgEntry->typePos & 0xF);
TextBoxType type = static_cast<TextBoxType>(msgEntry->typePos >> 4); TextBoxType type = static_cast<TextBoxType>(msgEntry->typePos >> 4);
// uint8_t icon = msgEntry->segment[1]; // uint8_t icon = msgEntry->segment[1];
std::string message = std::string(msgEntry->segment , msgEntry->msgSize); std::string message = std::string(msgEntry->segment, msgEntry->msgSize);
msg = CustomMessage(message, type, position); msg = CustomMessage(message, type, position);
// msg.Format(static_cast<ItemID>(icon)); // msg.Format(static_cast<ItemID>(icon));
return msg; return msg;
@ -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);
} }
@ -174,22 +164,22 @@ const std::string CustomMessage::GetForLanguage(uint8_t language, MessageFormat
return output; return output;
} }
const std::vector<std::string> CustomMessage::GetAllMessages(MessageFormat format) const{ const std::vector<std::string> CustomMessage::GetAllMessages(MessageFormat format) const {
std::vector<std::string> output = messages; std::vector<std::string> output = messages;
for (auto str : output){ for (auto str : output) {
ProcessMessageFormat(str, format); ProcessMessageFormat(str, format);
} }
return output; return output;
} }
void CustomMessage::ProcessMessageFormat(std::string& str, MessageFormat format) const { void CustomMessage::ProcessMessageFormat(std::string& str, MessageFormat format) const {
if (format == MF_FORMATTED){ if (format == MF_FORMATTED) {
FormatString(str); FormatString(str);
} else if (format == MF_CLEAN){ } else if (format == MF_CLEAN) {
CleanString(str); CleanString(str);
} else if (format == MF_AUTO_FORMAT){ } else if (format == MF_AUTO_FORMAT) {
AutoFormatString(str); AutoFormatString(str);
}else if (format == MF_ENCODE){ } else if (format == MF_ENCODE) {
EncodeColors(str); EncodeColors(str);
} }
} }
@ -198,14 +188,14 @@ const std::vector<bool>& CustomMessage::GetCapital() const {
return capital; return capital;
} }
void CustomMessage::SetCapital(std::vector<bool> capital_){ void CustomMessage::SetCapital(std::vector<bool> capital_) {
capital = capital_; capital = capital_;
} }
const std::vector<std::string>& CustomMessage::GetColors() const { const std::vector<std::string>& CustomMessage::GetColors() const {
return colors; return colors;
} }
void CustomMessage::SetColors(std::vector<std::string> colors_){ void CustomMessage::SetColors(std::vector<std::string> colors_) {
colors = colors_; colors = colors_;
} }
@ -213,7 +203,7 @@ const TextBoxType& CustomMessage::GetTextBoxType() const {
return type; return type;
} }
void CustomMessage::SetTextBoxType(TextBoxType boxType){ void CustomMessage::SetTextBoxType(TextBoxType boxType) {
type = boxType; type = boxType;
} }
@ -224,19 +214,19 @@ const TextBoxPosition& CustomMessage::GetTextBoxPosition() const {
CustomMessage CustomMessage::operator+(const CustomMessage& right) const { CustomMessage CustomMessage::operator+(const CustomMessage& right) const {
std::vector<std::string> newColors = colors; std::vector<std::string> newColors = colors;
std::vector<std::string> rColors = right.GetColors(); std::vector<std::string> rColors = right.GetColors();
for (auto color: rColors){ for (auto color : rColors) {
newColors.push_back(color); newColors.push_back(color);
} }
std::vector<bool> newCapital = capital; std::vector<bool> newCapital = capital;
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) {
@ -258,8 +248,8 @@ bool CustomMessage::operator==(const CustomMessage& operand) const {
} }
bool CustomMessage::operator==(const std::string& operand) const { bool CustomMessage::operator==(const std::string& operand) const {
for (auto str: messages){ for (auto str : messages) {
if (str == operand){ if (str == operand) {
return true; return true;
} }
} }
@ -291,7 +281,7 @@ void CustomMessage::Replace(std::string&& oldStr, CustomMessage newMessage) {
} }
void CustomMessage::Format(ItemID iid) { void CustomMessage::Format(ItemID iid) {
for (std::string &str : messages) { for (std::string& str : messages) {
str.insert(0, ITEM_OBTAINED(iid)); str.insert(0, ITEM_OBTAINED(iid));
size_t start_pos = 0; size_t start_pos = 0;
std::replace(str.begin(), str.end(), '&', NEWLINE()[0]); std::replace(str.begin(), str.end(), '&', NEWLINE()[0]);
@ -341,7 +331,7 @@ void CustomMessage::FormatString(std::string& str) const {
str += MESSAGE_END(); str += MESSAGE_END();
} }
void DeleteControlCode(std::string& str, std::string code){ void DeleteControlCode(std::string& str, std::string code) {
size_t start_pos = 0; size_t start_pos = 0;
while ((start_pos = str.find(code, start_pos)) != std::string::npos) { while ((start_pos = str.find(code, start_pos)) != std::string::npos) {
str.replace(start_pos, code.length(), ""); str.replace(start_pos, code.length(), "");
@ -384,8 +374,8 @@ static size_t NextLineLength(const std::string* textStr, const size_t lastNewlin
// Skip colour control characters. // Skip colour control characters.
nextPosJump = 2; nextPosJump = 2;
} else if (textStr->at(currentPos) == '\x1E') { } else if (textStr->at(currentPos) == '\x1E') {
//For the high score char, we have to take the next Char, then use that to get a worst case scenario. // For the high score char, we have to take the next Char, then use that to get a worst case scenario.
if (textStr->at(currentPos+1) == '\x01'){ if (textStr->at(currentPos + 1) == '\x01') {
totalPixelWidth += 28; totalPixelWidth += 28;
} }
nextPosJump = 2; nextPosJump = 2;
@ -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;
} }
@ -488,19 +479,19 @@ void CustomMessage::AutoFormatString(std::string& str) const {
const size_t lastSpace = str.rfind(' ', lastNewline + lineLength); const size_t lastSpace = str.rfind(' ', lastNewline + lineLength);
size_t waitForInput = str.find(WAIT_FOR_INPUT()[0], lastNewline); size_t waitForInput = str.find(WAIT_FOR_INPUT()[0], lastNewline);
size_t newLine = FindNEWLINE(str, lastNewline); size_t newLine = FindNEWLINE(str, lastNewline);
if (carrot < waitForInput){ if (carrot < waitForInput) {
waitForInput = carrot; waitForInput = carrot;
} }
if (ampersand < newLine){ if (ampersand < newLine) {
newLine = ampersand; newLine = ampersand;
} }
if (lineCount != 3 && yesNo < lastNewline + lineLength && yesNo < waitForInput && yesNo < newLine){ if (lineCount != 3 && yesNo < lastNewline + lineLength && yesNo < waitForInput && yesNo < newLine) {
if (lineCount >= 4){ if (lineCount >= 4) {
str.replace(yesNo, 1, "^&&\x1B"); str.replace(yesNo, 1, "^&&\x1B");
lineCount = 3; lineCount = 3;
lastNewline = yesNo + 3; lastNewline = yesNo + 3;
} else { } else {
while(lineCount < 3){ while (lineCount < 3) {
str.replace(yesNo, 1, "&\x1B"); str.replace(yesNo, 1, "&\x1B");
yesNo++; yesNo++;
lineCount++; lineCount++;
@ -508,7 +499,7 @@ void CustomMessage::AutoFormatString(std::string& str) const {
lastNewline = yesNo; lastNewline = yesNo;
} }
} else { } else {
if (lineCount < 4){ if (lineCount < 4) {
// replace '&' first if it's within the newline range // replace '&' first if it's within the newline range
if (newLine < lastNewline + lineLength) { if (newLine < lastNewline + lineLength) {
lastNewline = newLine + 1; lastNewline = newLine + 1;
@ -529,9 +520,9 @@ void CustomMessage::AutoFormatString(std::string& str) const {
} else { } else {
const size_t lastColor = str.rfind("\x05"s, lastNewline + lineLength); const size_t lastColor = str.rfind("\x05"s, lastNewline + lineLength);
std::string colorText = ""; std::string colorText = "";
//check if we are on a non default colour, as ^ resets it, and readd if needed // check if we are on a non default colour, as ^ resets it, and readd if needed
if (lastColor != std::string::npos && str[lastColor+1] != 0){ if (lastColor != std::string::npos && str[lastColor + 1] != 0) {
colorText = "\x05"s + str[lastColor+1]; colorText = "\x05"s + str[lastColor + 1];
} }
// replace '&' first if it's within the newline range // replace '&' first if it's within the newline range
if (ampersand < lastNewline + lineLength) { if (ampersand < lastNewline + lineLength) {
@ -564,7 +555,7 @@ void CustomMessage::AutoFormatString(std::string& str) const {
str += MESSAGE_END(); str += MESSAGE_END();
} }
void CustomMessage::InsertNumber(uint8_t num){ void CustomMessage::InsertNumber(uint8_t num) {
for (std::string& str : messages) { for (std::string& str : messages) {
size_t firstBar = str.find('|'); size_t firstBar = str.find('|');
if (firstBar != std::string::npos) { if (firstBar != std::string::npos) {
@ -581,12 +572,11 @@ void CustomMessage::InsertNumber(uint8_t num){
} }
} }
} }
//remove the remaining bar // remove the remaining bar
this->Replace("|", ""); this->Replace("|", "");
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]);
@ -625,7 +615,7 @@ const char* Interface_ReplaceSpecialCharacters(char text[]) {
} }
void CustomMessage::EncodeColors(std::string& str) const { void CustomMessage::EncodeColors(std::string& str) const {
for (std::string color: colors) { for (std::string color : colors) {
if (const size_t firstHashtag = str.find('#'); firstHashtag != std::string::npos) { if (const size_t firstHashtag = str.find('#'); firstHashtag != std::string::npos) {
str.replace(firstHashtag, 1, colorToPercent.at(color)); str.replace(firstHashtag, 1, colorToPercent.at(color));
if (const size_t secondHashtag = str.find('#', firstHashtag + 1); secondHashtag != std::string::npos) { if (const size_t secondHashtag = str.find('#', firstHashtag + 1); secondHashtag != std::string::npos) {
@ -664,13 +654,13 @@ void CustomMessage::ReplaceAltarIcons(std::string& str) const {
} }
} }
void CustomMessage::InsertNames(std::vector<CustomMessage> toInsert){ void CustomMessage::InsertNames(std::vector<CustomMessage> toInsert) {
for(uint8_t a = 0; a < toInsert.size(); a++){ for (uint8_t a = 0; a < toInsert.size(); a++) {
CustomMessage temp = toInsert[a]; CustomMessage temp = toInsert[a];
if ((capital.size() > a) && (capital[a] = true)){ if ((capital.size() > a) && (capital[a] = true)) {
temp.Capitalize(); temp.Capitalize();
} }
Replace("[[" + std::to_string(a+1) + "]]", temp); Replace("[[" + std::to_string(a + 1) + "]]", temp);
} }
} }
@ -735,13 +725,13 @@ CustomMessage CustomMessageManager::RetrieveMessage(std::string tableID, uint16_
} }
CustomMessage message = foundMessage->second; CustomMessage message = foundMessage->second;
if (format == MF_FORMATTED){ if (format == MF_FORMATTED) {
message.Format(); message.Format();
} else if (format == MF_AUTO_FORMAT){ } else if (format == MF_AUTO_FORMAT) {
message.AutoFormat(); message.AutoFormat();
} else if (format == MF_CLEAN){ } else if (format == MF_CLEAN) {
message.Clean(); message.Clean();
} else if (format == MF_ENCODE){ } else if (format == MF_ENCODE) {
message.Encode(); message.Encode();
} }

View file

@ -20,7 +20,7 @@
#define QM_YELLOW "\x46" #define QM_YELLOW "\x46"
#define QM_BLACK "\x47" #define QM_BLACK "\x47"
#define HS_HORSE_ARCHERY "\x00"s //HS_HBA is an enum already #define HS_HORSE_ARCHERY "\x00"s // HS_HBA is an enum already
typedef enum { typedef enum {
MF_FORMATTED, MF_FORMATTED,
@ -41,21 +41,24 @@ 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);
static std::string MESSAGE_END() ; static std::string MESSAGE_END();
static std::string ITEM_OBTAINED(uint8_t x) ; static std::string ITEM_OBTAINED(uint8_t x);
static std::string NEWLINE() ; static std::string NEWLINE();
static std::string COLOR(std::string x) ; static std::string COLOR(std::string x);
static std::string POINTS(std::string x) ;//HIGH_SCORE is also a macro static std::string POINTS(std::string x); // HIGH_SCORE is also a macro
static std::string WAIT_FOR_INPUT() ; static std::string WAIT_FOR_INPUT();
static std::string PLAYER_NAME() ; static std::string PLAYER_NAME();
const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const; const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const;
const std::string GetFrench(MessageFormat format = MF_FORMATTED) const; const std::string GetFrench(MessageFormat format = MF_FORMATTED) const;
@ -200,7 +203,7 @@ class CustomMessage {
void CleanString(std::string& str) const; void CleanString(std::string& str) const;
private: private:
std::vector<std::string> messages = {"","",""}; std::vector<std::string> messages = { "", "", "" };
TextBoxType type = TEXTBOX_TYPE_BLACK; TextBoxType type = TEXTBOX_TYPE_BLACK;
TextBoxPosition position = TEXTBOX_POS_BOTTOM; TextBoxPosition position = TEXTBOX_POS_BOTTOM;
std::vector<std::string> colors = {}; std::vector<std::string> colors = {};

File diff suppressed because it is too large Load diff

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,
@ -201,13 +202,14 @@ void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t lan
FindMessage(play, textId, language); FindMessage(play, textId, language);
msgCtx->msgLength = static_cast<int32_t>(font->msgLength); msgCtx->msgLength = static_cast<int32_t>(font->msgLength);
const uintptr_t src = font->msgOffset; const uintptr_t src = font->msgOffset;
memcpy(font->msgBuf, reinterpret_cast<void const *>(src), font->msgLength); memcpy(font->msgBuf, reinterpret_cast<void const*>(src), font->msgLength);
} else { } else {
constexpr int maxBufferSize = sizeof(font->msgBuf); constexpr int maxBufferSize = sizeof(font->msgBuf);
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,9 +25,8 @@ 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";
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
@ -37,12 +36,12 @@ public:
virtual ~MessageViewer() = default; virtual ~MessageViewer() = default;
private: private:
void DisplayExistingMessage() const; void DisplayExistingMessage() const;
void DisplayCustomMessage() const; void DisplayCustomMessage() const;
static constexpr uint16_t MAX_STRING_SIZE = 1024; static constexpr uint16_t MAX_STRING_SIZE = 1024;
static constexpr std::array<const char*, LANGUAGE_MAX> mLanguages = {"English", "German", "French"}; static constexpr std::array<const char*, LANGUAGE_MAX> mLanguages = { "English", "German", "French" };
static constexpr int HEXADECIMAL = 0; static constexpr int HEXADECIMAL = 0;
static constexpr int DECIMAL = 1; static constexpr int DECIMAL = 1;
char* mTableIdBuf; char* mTableIdBuf;
@ -57,6 +56,5 @@ private:
bool mDisplayCustomMessageClicked = false; bool mDisplayCustomMessageClicked = false;
}; };
#endif //__cplusplus #endif //__cplusplus
#endif //CUSTOMMESSAGEDEBUGGER_H #endif // CUSTOMMESSAGEDEBUGGER_H

View file

@ -6,12 +6,12 @@
class SohStatsWindow : public Ship::GuiWindow { class SohStatsWindow : public Ship::GuiWindow {
public: public:
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
~SohStatsWindow() {}; ~SohStatsWindow(){};
protected: protected:
void InitElement() override {}; void InitElement() override{};
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };
#endif // SOH_STATS_H #endif // SOH_STATS_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();
@ -103,7 +98,7 @@ void PopulateActorDropdown(int i, std::vector<Actor*>& data) {
} }
} }
//actors that don't use params at all // actors that don't use params at all
static std::vector<u16> noParamsActors = { static std::vector<u16> noParamsActors = {
ACTOR_ARMS_HOOK, ACTOR_ARMS_HOOK,
ACTOR_ARROW_FIRE, ACTOR_ARROW_FIRE,
@ -259,7 +254,7 @@ void CreateActorSpecificData() {
if (params == 0) { if (params == 0) {
params = -2; params = -2;
} }
//the + 2 is because the params are -2 & -1 instead of 0 & 1 // the + 2 is because the params are -2 & -1 instead of 0 & 1
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))) {
return selectedItem - 2; return selectedItem - 2;
@ -333,7 +328,7 @@ void CreateActorSpecificData() {
if (params == 0) { if (params == 0) {
params = 0x40; params = 0x40;
} }
//the - 0x40 is because the params are 0x40 & 0x41 instead of 0 & 1 // the - 0x40 is because the params are 0x40 & 0x41 instead of 0 & 1
int selectedItem = params - 0x40; int selectedItem = params - 0x40;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem + 0x40; return selectedItem + 0x40;
@ -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))) {
@ -599,9 +543,9 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_EN_CLEAR_TAG] = [](s16 params) -> s16 { actorSpecificData[ACTOR_EN_CLEAR_TAG] = [](s16 params) -> s16 {
static const char* items[] = { static const char* items[] = {
"Cutscene", //0 "Cutscene", // 0
"Normal", //1 "Normal", // 1
"Laser", //100 "Laser", // 100
}; };
int selectedItem = params == 100 ? 2 : params; int selectedItem = params == 100 ? 2 : params;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
@ -613,7 +557,7 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_EN_BOMBF] = [](s16 params) -> s16 { actorSpecificData[ACTOR_EN_BOMBF] = [](s16 params) -> s16 {
static const char* items[] = { "Flower", "Body", "Explosion" }; static const char* items[] = { "Flower", "Body", "Explosion" };
//the + 1 is because the params are -1, 0 & 1 instead of 0, 1 & 2 // the + 1 is because the params are -1, 0 & 1 instead of 0, 1 & 2
int selectedItem = params + 1; int selectedItem = params + 1;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) { if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem - 1; return selectedItem - 1;
@ -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;
@ -921,7 +852,7 @@ void ActorViewerWindow::DrawElement() {
static Actor* display; static Actor* display;
static Actor empty{}; static Actor empty{};
static Actor* fetch = NULL; static Actor* fetch = NULL;
static ActorInfo newActor = {0,0, {0, 0, 0}, {0, 0, 0}}; static ActorInfo newActor = { 0, 0, { 0, 0, 0 }, { 0, 0, 0 } };
static bool needs_reset = false; static bool needs_reset = false;
static ImU16 one = 1; static ImU16 one = 1;
static int actor; static int actor;
@ -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) {
@ -1094,7 +1040,7 @@ void ActorViewerWindow::DrawElement() {
} }
if (ImGui::TreeNode("New...")) { if (ImGui::TreeNode("New...")) {
//ImGui::PushItemWidth(ImGui::GetFontSize() * 10); // ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
if (InputString("Search Actor", &searchString, InputOptions().Color(THEME_COLOR))) { if (InputString("Search Actor", &searchString, InputOptions().Color(THEME_COLOR))) {
actors = GetActorsWithDescriptionContainingString(searchString); actors = GetActorsWithDescriptionContainingString(searchString);
@ -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

@ -8,5 +8,5 @@ class ActorViewerWindow : public Ship::GuiWindow {
void DrawElement() override; void DrawElement() override;
void InitElement() override; void InitElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };

View file

@ -20,7 +20,7 @@ extern "C" {
extern PlayState* gPlayState; extern PlayState* gPlayState;
} }
typedef enum ColRenderSetting { ColRenderDisabled, ColRenderSolid, ColRenderTransparent } ColRenderSetting ; typedef enum ColRenderSetting { ColRenderDisabled, ColRenderSolid, ColRenderTransparent } ColRenderSetting;
static std::unordered_map<int32_t, const char*> ColRenderSettingNames = { static std::unordered_map<int32_t, const char*> ColRenderSettingNames = {
{ ColRenderDisabled, "Disabled" }, { ColRenderDisabled, "Disabled" },
@ -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();
@ -210,9 +232,9 @@ void CreateSphereFace(std::vector<std::tuple<size_t, size_t, size_t>>& faces, in
// Create 3 new verticies at the midpoints // Create 3 new verticies at the midpoints
Vec3f vs[3] = { Vec3f vs[3] = {
Vec3f{(v0.n.ob[0] + v1.n.ob[0]) / 2.0f, (v0.n.ob[1] + v1.n.ob[1]) / 2.0f, (v0.n.ob[2] + v1.n.ob[2]) / 2.0f}, Vec3f{ (v0.n.ob[0] + v1.n.ob[0]) / 2.0f, (v0.n.ob[1] + v1.n.ob[1]) / 2.0f, (v0.n.ob[2] + v1.n.ob[2]) / 2.0f },
Vec3f{(v1.n.ob[0] + v2.n.ob[0]) / 2.0f, (v1.n.ob[1] + v2.n.ob[1]) / 2.0f, (v1.n.ob[2] + v2.n.ob[2]) / 2.0f}, Vec3f{ (v1.n.ob[0] + v2.n.ob[0]) / 2.0f, (v1.n.ob[1] + v2.n.ob[1]) / 2.0f, (v1.n.ob[2] + v2.n.ob[2]) / 2.0f },
Vec3f{(v2.n.ob[0] + v0.n.ob[0]) / 2.0f, (v2.n.ob[1] + v0.n.ob[1]) / 2.0f, (v2.n.ob[2] + v0.n.ob[2]) / 2.0f} Vec3f{ (v2.n.ob[0] + v0.n.ob[0]) / 2.0f, (v2.n.ob[1] + v0.n.ob[1]) / 2.0f, (v2.n.ob[2] + v0.n.ob[2]) / 2.0f }
}; };
// Normalize vertex positions so they are on the sphere // Normalize vertex positions so they are on the sphere
@ -237,20 +259,20 @@ void CreateSphereData() {
float d = (1.0f + sqrtf(5.0f)) / 2.0f; float d = (1.0f + sqrtf(5.0f)) / 2.0f;
// Create the 12 starting verticies, 4 on each rectangle // Create the 12 starting verticies, 4 on each rectangle
base.emplace_back(Vec3f({-1, d, 0})); base.emplace_back(Vec3f({ -1, d, 0 }));
base.emplace_back(Vec3f({1, d, 0})); base.emplace_back(Vec3f({ 1, d, 0 }));
base.emplace_back(Vec3f({-1, -d, 0})); base.emplace_back(Vec3f({ -1, -d, 0 }));
base.emplace_back(Vec3f({1, -d, 0})); base.emplace_back(Vec3f({ 1, -d, 0 }));
base.emplace_back(Vec3f({0, -1, d})); base.emplace_back(Vec3f({ 0, -1, d }));
base.emplace_back(Vec3f({0, 1, d})); base.emplace_back(Vec3f({ 0, 1, d }));
base.emplace_back(Vec3f({0, -1, -d})); base.emplace_back(Vec3f({ 0, -1, -d }));
base.emplace_back(Vec3f({0, 1, -d})); base.emplace_back(Vec3f({ 0, 1, -d }));
base.emplace_back(Vec3f({d, 0, -1})); base.emplace_back(Vec3f({ d, 0, -1 }));
base.emplace_back(Vec3f({d, 0, 1})); base.emplace_back(Vec3f({ d, 0, 1 }));
base.emplace_back(Vec3f({-d, 0, -1})); base.emplace_back(Vec3f({ -d, 0, -1 }));
base.emplace_back(Vec3f({-d, 0, 1})); base.emplace_back(Vec3f({ -d, 0, 1 }));
// Normalize verticies so they are on the unit sphere // Normalize verticies so they are on the unit sphere
for (Vec3f& v : base) { for (Vec3f& v : base) {
@ -349,7 +371,7 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
// Draws a dynapoly structure (scenes or Bg Actors) // Draws a dynapoly structure (scenes or Bg Actors)
void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) { void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
Color_RGBA8 color = {255, 255, 255, 255}; Color_RGBA8 color = { 255, 255, 255, 255 };
uint32_t lastColorR = color.r; uint32_t lastColorR = color.r;
uint32_t lastColorG = color.g; uint32_t lastColorG = color.g;
@ -367,7 +389,7 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
if (SurfaceType_IsHookshotSurface(&gPlayState->colCtx, poly, bgId)) { if (SurfaceType_IsHookshotSurface(&gPlayState->colCtx, poly, bgId)) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot.Value"), { 128, 128, 255, 255 }); color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot.Value"), { 128, 128, 255, 255 });
} else if (func_80041D94(&gPlayState->colCtx, poly, bgId) > 0x01) { } else if (func_80041D94(&gPlayState->colCtx, poly, bgId) > 0x01) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable.Value"), {192, 0, 192, 255}); color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable.Value"), { 192, 0, 192, 255 });
} else if (func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x0C) { } else if (func_80041E80(&gPlayState->colCtx, poly, bgId) == 0x0C) {
color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid.Value"), { 255, 0, 0, 255 }); color = CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorVoid.Value"), { 255, 0, 0, 255 });
} else if (SurfaceType_GetSceneExitIndex(&gPlayState->colCtx, poly, bgId) || } else if (SurfaceType_GetSceneExitIndex(&gPlayState->colCtx, poly, bgId) ||
@ -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 {
@ -15,7 +11,7 @@ class ColViewerWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };
#endif #endif

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();
@ -90,13 +90,13 @@ void DrawGroupWithBorder(T&& drawFunc, std::string section) {
char z2ASCII(int code) { char z2ASCII(int code) {
int ret; int ret;
if (code < 10) { //Digits if (code < 10) { // Digits
ret = code + 0x30; ret = code + 0x30;
} else if (code >= 10 && code < 36) { //Uppercase letters } else if (code >= 10 && code < 36) { // Uppercase letters
ret = code + 0x37; ret = code + 0x37;
} else if (code >= 36 && code < 62) { //Lowercase letters } else if (code >= 36 && code < 62) { // Lowercase letters
ret = code + 0x3D; ret = code + 0x3D;
} else if (code == 62) { //Space } else if (code == 62) { // Space
ret = code - 0x1E; ret = code - 0x1E;
} else if (code == 63 || code == 64) { // _ and . } else if (code == 63 || code == 64) { // _ and .
ret = code - 0x12; ret = code - 0x12;
@ -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;
} }
@ -212,7 +214,7 @@ void DrawInfoTab() {
Tooltip("Current rupees"); Tooltip("Current rupees");
PopStyleInput(); PopStyleInput();
SliderInt("Time", (int32_t*) &gSaveContext.dayTime, intSliderOptionsBase.Min(0).Max(0xFFFF).Tooltip("Time of day")); SliderInt("Time", (int32_t*)&gSaveContext.dayTime, intSliderOptionsBase.Min(0).Max(0xFFFF).Tooltip("Time of day"));
if (Button("Dawn", buttonOptionsBase)) { if (Button("Dawn", buttonOptionsBase)) {
gSaveContext.dayTime = 0x4000; gSaveContext.dayTime = 0x4000;
} }
@ -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,88 +291,98 @@ 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")) {
for (int i = 0; i < 7; i++) { for (int i = 0; i < 7; i++) {
if(i == 2 && ImGui::TreeNode("Fishing") ){ //fishing has a few more flags to it if (i == 2 && ImGui::TreeNode("Fishing")) { // fishing has a few more flags to it
u8 fishSize = gSaveContext.highScores[i] & 0x7F; u8 fishSize = gSaveContext.highScores[i] & 0x7F;
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
if(ImGui::InputScalar("Child Size Record",ImGuiDataType_U8,&fishSize)){ if (ImGui::InputScalar("Child Size Record", ImGuiDataType_U8, &fishSize)) {
gSaveContext.highScores[i]&=~0x7F; gSaveContext.highScores[i] &= ~0x7F;
gSaveContext.highScores[i]|=fishSize & 0x7F; gSaveContext.highScores[i] |= fishSize & 0x7F;
} }
char fishMsg[64]; char fishMsg[64];
std::sprintf(fishMsg,"Weight: %2.0f lbs",((SQ(fishSize)*.0036)+.5)); std::sprintf(fishMsg, "Weight: %2.0f lbs", ((SQ(fishSize) * .0036) + .5));
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);
} }
fishSize=(gSaveContext.highScores[i] & 0x7F000000)>>0x18; fishSize = (gSaveContext.highScores[i] & 0x7F000000) >> 0x18;
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
if(ImGui::InputScalar("Adult Size Record",ImGuiDataType_U8,&fishSize)){ if (ImGui::InputScalar("Adult Size Record", ImGuiDataType_U8, &fishSize)) {
gSaveContext.highScores[i]&=~0x7F000000; gSaveContext.highScores[i] &= ~0x7F000000;
gSaveContext.highScores[i]|=(fishSize & 0x7F) << 0x18; gSaveContext.highScores[i] |= (fishSize & 0x7F) << 0x18;
} }
std::sprintf(fishMsg,"Weight: %2.0f lbs",((SQ(fishSize)*.0036)+.5)); std::sprintf(fishMsg, "Weight: %2.0f lbs", ((SQ(fishSize) * .0036) + .5));
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);
} }
fishSize=(gSaveContext.highScores[i] & 0xFF0000)>>16; fishSize = (gSaveContext.highScores[i] & 0xFF0000) >> 16;
PushStyleInput(THEME_COLOR); PushStyleInput(THEME_COLOR);
if(ImGui::InputScalar("Times Played",ImGuiDataType_U8,&fishSize)){ if (ImGui::InputScalar("Times Played", ImGuiDataType_U8, &fishSize)) {
gSaveContext.highScores[i]&=~0xFF0000; gSaveContext.highScores[i] &= ~0xFF0000;
gSaveContext.highScores[i]|=(fishSize) << 16; gSaveContext.highScores[i] |= (fishSize) << 16;
} }
Tooltip("Determines weather and school size during dawn/dusk."); Tooltip("Determines weather and school size during dawn/dusk.");
PopStyleInput(); PopStyleInput();
@ -378,7 +391,7 @@ void DrawInfoTab() {
continue; continue;
} }
if (i == 5 || i == 2) { //HS_UNK_05 is unused if (i == 5 || i == 2) { // HS_UNK_05 is unused
continue; continue;
} }
std::string minigameLbl = minigameHS[i]; std::string minigameLbl = minigameHS[i];
@ -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);
} }
@ -532,7 +553,7 @@ void DrawFlagTableArray16(const FlagTable& flagTable, uint16_t row, uint16_t& fl
bool hasDescription = !!flagTable.flagDescriptions.contains(row * 16 + flagIndex); bool hasDescription = !!flagTable.flagDescriptions.contains(row * 16 + flagIndex);
uint32_t bitMask = 1 << flagIndex; uint32_t bitMask = 1 << flagIndex;
ImVec4 themeColor = ColorValues.at(THEME_COLOR); ImVec4 themeColor = ColorValues.at(THEME_COLOR);
ImVec4 colorDark = { themeColor.x * 0.4f, themeColor.y * 0.4f, themeColor.z * 0.4f , themeColor.z }; ImVec4 colorDark = { themeColor.x * 0.4f, themeColor.y * 0.4f, themeColor.z * 0.4f, themeColor.z };
PushStyleCheckbox(hasDescription ? themeColor : colorDark); PushStyleCheckbox(hasDescription ? themeColor : colorDark);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0f, 3.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0f, 3.0f));
bool flag = (flags & bitMask) != 0; bool flag = (flags & bitMask) != 0;
@ -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!");
@ -1547,10 +1643,13 @@ void DrawPlayerTab() {
} }
void ResetBaseOptions() { 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" },
@ -477,8 +512,8 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_MERCHANTS_CARPET_SALESMAN, "RAND_INF_MERCHANTS_CARPET_SALESMAN" }, { RAND_INF_MERCHANTS_CARPET_SALESMAN, "RAND_INF_MERCHANTS_CARPET_SALESMAN" },
{ RAND_INF_MERCHANTS_MEDIGORON, "RAND_INF_MERCHANTS_MEDIGORON" }, { RAND_INF_MERCHANTS_MEDIGORON, "RAND_INF_MERCHANTS_MEDIGORON" },
{ RAND_INF_MERCHANTS_GRANNYS_SHOP, "RAND_INF_MERCHANTS_GRANNY_SHOP"}, { RAND_INF_MERCHANTS_GRANNYS_SHOP, "RAND_INF_MERCHANTS_GRANNY_SHOP" },
{ RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN, "RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN"}, { RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN, "RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN" },
{ RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO, "ADULT_TRADES_LW_TRADE_COJIRO" }, { RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO, "ADULT_TRADES_LW_TRADE_COJIRO" },
{ RAND_INF_ADULT_TRADES_GV_TRADE_SAW, "ADULT_TRADES_GV_TRADE_SAW" }, { RAND_INF_ADULT_TRADES_GV_TRADE_SAW, "ADULT_TRADES_GV_TRADE_SAW" },
@ -489,7 +524,7 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD, "KAK_100_GOLD_SKULLTULA_REWARD" }, { RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD, "KAK_100_GOLD_SKULLTULA_REWARD" },
{ RAND_INF_GREG_FOUND, "RAND_INF_GREG_FOUND" }, { RAND_INF_GREG_FOUND, "RAND_INF_GREG_FOUND" },
{ RAND_INF_TOT_MASTER_SWORD, "RAND_INF_TOT_MASTER_SWORD"}, { RAND_INF_TOT_MASTER_SWORD, "RAND_INF_TOT_MASTER_SWORD" },
{ RAND_INF_CHILD_FISHING, "RAND_INF_CHILD_FISHING" }, { RAND_INF_CHILD_FISHING, "RAND_INF_CHILD_FISHING" },
{ RAND_INF_ADULT_FISHING, "RAND_INF_ADULT_FISHING" }, { RAND_INF_ADULT_FISHING, "RAND_INF_ADULT_FISHING" },
{ RAND_INF_10_BIG_POES, "RAND_INF_10_BIG_POES" }, { RAND_INF_10_BIG_POES, "RAND_INF_10_BIG_POES" },
@ -505,11 +540,11 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" }, { RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" },
{ RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" }, { RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" },
{ RAND_INF_HAS_OCARINA_A, "RAND_INF_HAS_OCARINA_A"}, { RAND_INF_HAS_OCARINA_A, "RAND_INF_HAS_OCARINA_A" },
{ RAND_INF_HAS_OCARINA_C_UP, "RAND_INF_HAS_OCARINA_C_UP" }, { RAND_INF_HAS_OCARINA_C_UP, "RAND_INF_HAS_OCARINA_C_UP" },
{ RAND_INF_HAS_OCARINA_C_DOWN, "RAND_INF_HAS_OCARINA_C_DOWN" }, { RAND_INF_HAS_OCARINA_C_DOWN, "RAND_INF_HAS_OCARINA_C_DOWN" },
{ RAND_INF_HAS_OCARINA_C_LEFT, "RAND_INF_HAS_OCARINA_C_LEFT"}, { RAND_INF_HAS_OCARINA_C_LEFT, "RAND_INF_HAS_OCARINA_C_LEFT" },
{ RAND_INF_HAS_OCARINA_C_RIGHT, "RAND_INF_HAS_OCARINA_C_RIGHT"}, { RAND_INF_HAS_OCARINA_C_RIGHT, "RAND_INF_HAS_OCARINA_C_RIGHT" },
{ RAND_INF_KF_LINKS_HOUSE_POT, "RAND_INF_KF_LINKS_HOUSE_POT" }, { RAND_INF_KF_LINKS_HOUSE_POT, "RAND_INF_KF_LINKS_HOUSE_POT" },
{ RAND_INF_KF_TWINS_HOUSE_POT_1, "RAND_INF_KF_TWINS_HOUSE_POT_1" }, { RAND_INF_KF_TWINS_HOUSE_POT_1, "RAND_INF_KF_TWINS_HOUSE_POT_1" },
@ -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" },
@ -1661,7 +1720,7 @@ const std::vector<std::string> state1 = {
"In Water", "In Water",
"In Item Cutscene", "In Item Cutscene",
"In Cutscene", "In Cutscene",
"30", //Unknown "30", // Unknown
"Floor collision disabled", "Floor collision disabled",
}; };
@ -1717,5 +1776,5 @@ class SaveEditorWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };

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

@ -8,5 +8,5 @@ class DLViewerWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };

View file

@ -6,5 +6,5 @@ class HookDebuggerWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };

View file

@ -1,14 +1,14 @@
#include "performanceTimer.h" #include "performanceTimer.h"
void StartPerformanceTimer(TimerID timer){ void StartPerformanceTimer(TimerID timer) {
timeStarted[timer] = std::chrono::high_resolution_clock::now(); timeStarted[timer] = std::chrono::high_resolution_clock::now();
} }
void StopPerformanceTimer(TimerID timer){ void StopPerformanceTimer(TimerID timer) {
totalTimes[timer] += (std::chrono::high_resolution_clock::now() - timeStarted[timer]); totalTimes[timer] += (std::chrono::high_resolution_clock::now() - timeStarted[timer]);
} }
std::chrono::duration<double, std::milli> GetPerformanceTimer(TimerID timer){ std::chrono::duration<double, std::milli> GetPerformanceTimer(TimerID timer) {
return totalTimes[timer]; return totalTimes[timer];
} }
@ -16,6 +16,6 @@ void ResetPerformanceTimer(TimerID timer) {
totalTimes[timer] = {}; totalTimes[timer] = {};
} }
void ResetPerformanceTimers(){ void ResetPerformanceTimers() {
totalTimes = {}; totalTimes = {};
} }

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

@ -39,7 +39,7 @@ class ValueViewerWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };
#endif #endif

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
@ -162,8 +200,8 @@ static int enemiesToRandomize[] = {
ACTOR_EN_CROW, // Guay ACTOR_EN_CROW, // Guay
}; };
extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *posX, f32 *posY, f32 *posZ, int16_t *rotX, extern "C" 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) { int16_t* rotY, int16_t* rotZ, int16_t* params) {
uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(play->sceneNum); uint32_t isMQ = ResourceMgr_IsSceneMasterQuest(play->sceneNum);
@ -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

@ -47,75 +47,73 @@ GameInteractionEffectQueryResult RemovableGameInteractionEffect::Remove() {
namespace GameInteractionEffect { namespace GameInteractionEffect {
// MARK: - Flags // MARK: - Flags
GameInteractionEffectQueryResult SetSceneFlag::CanBeApplied() { GameInteractionEffectQueryResult SetSceneFlag::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
void SetSceneFlag::_Apply() { void SetSceneFlag::_Apply() {
GameInteractor::RawAction::SetSceneFlag(parameters[0], parameters[1], parameters[2]); GameInteractor::RawAction::SetSceneFlag(parameters[0], parameters[1], parameters[2]);
} }
GameInteractionEffectQueryResult UnsetSceneFlag::CanBeApplied() { GameInteractionEffectQueryResult UnsetSceneFlag::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
void UnsetSceneFlag::_Apply() { void UnsetSceneFlag::_Apply() {
GameInteractor::RawAction::UnsetSceneFlag(parameters[0], parameters[1], parameters[2]); GameInteractor::RawAction::UnsetSceneFlag(parameters[0], parameters[1], parameters[2]);
} }
GameInteractionEffectQueryResult SetFlag::CanBeApplied() { GameInteractionEffectQueryResult SetFlag::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
void SetFlag::_Apply() { void SetFlag::_Apply() {
GameInteractor::RawAction::SetFlag(parameters[0], parameters[1]); GameInteractor::RawAction::SetFlag(parameters[0], parameters[1]);
} }
GameInteractionEffectQueryResult UnsetFlag::CanBeApplied() { GameInteractionEffectQueryResult UnsetFlag::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
void UnsetFlag::_Apply() { void UnsetFlag::_Apply() {
GameInteractor::RawAction::UnsetFlag(parameters[0], parameters[1]); GameInteractor::RawAction::UnsetFlag(parameters[0], parameters[1]);
} }
// MARK: - ModifyHeartContainers // MARK: - ModifyHeartContainers
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;
} }
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
void ModifyHeartContainers::_Apply() { void ModifyHeartContainers::_Apply() {
GameInteractor::RawAction::AddOrRemoveHealthContainers(parameters[0]); GameInteractor::RawAction::AddOrRemoveHealthContainers(parameters[0]);
} }
// MARK: - FillMagic // MARK: - FillMagic
GameInteractionEffectQueryResult FillMagic::CanBeApplied() { GameInteractionEffectQueryResult FillMagic::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if (!gSaveContext.isMagicAcquired || gSaveContext.magic >= ((gSaveContext.isDoubleMagicAcquired + 1) * 48)) { } else if (!gSaveContext.isMagicAcquired || gSaveContext.magic >= ((gSaveContext.isDoubleMagicAcquired + 1) * 48)) {
@ -123,13 +121,13 @@ namespace GameInteractionEffect {
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void FillMagic::_Apply() { void FillMagic::_Apply() {
GameInteractor::RawAction::AddOrRemoveMagic(96); GameInteractor::RawAction::AddOrRemoveMagic(96);
} }
// MARK: - EmptyMagic // MARK: - EmptyMagic
GameInteractionEffectQueryResult EmptyMagic::CanBeApplied() { GameInteractionEffectQueryResult EmptyMagic::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if (!gSaveContext.isMagicAcquired || gSaveContext.magic <= 0) { } else if (!gSaveContext.isMagicAcquired || gSaveContext.magic <= 0) {
@ -137,408 +135,406 @@ namespace GameInteractionEffect {
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void EmptyMagic::_Apply() { void EmptyMagic::_Apply() {
GameInteractor::RawAction::AddOrRemoveMagic(-96); GameInteractor::RawAction::AddOrRemoveMagic(-96);
} }
// MARK: - ModifyRupees // MARK: - ModifyRupees
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;
} }
} }
void ModifyRupees::_Apply() { void ModifyRupees::_Apply() {
Rupees_ChangeBy(parameters[0]); Rupees_ChangeBy(parameters[0]);
} }
// MARK: - NoUI // MARK: - NoUI
GameInteractionEffectQueryResult NoUI::CanBeApplied() { GameInteractionEffectQueryResult NoUI::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void NoUI::_Apply() { void NoUI::_Apply() {
GameInteractor::State::NoUIActive = 1; GameInteractor::State::NoUIActive = 1;
} }
void NoUI::_Remove() { void NoUI::_Remove() {
GameInteractor::State::NoUIActive = 0; GameInteractor::State::NoUIActive = 0;
} }
// MARK: - ModifyGravity // MARK: - ModifyGravity
GameInteractionEffectQueryResult ModifyGravity::CanBeApplied() { GameInteractionEffectQueryResult ModifyGravity::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void ModifyGravity::_Apply() { void ModifyGravity::_Apply() {
GameInteractor::State::GravityLevel = (GIGravityLevel)parameters[0]; GameInteractor::State::GravityLevel = (GIGravityLevel)parameters[0];
} }
void ModifyGravity::_Remove() { void ModifyGravity::_Remove() {
GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL; GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL;
} }
// MARK: - ModifyHealth // MARK: - ModifyHealth
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;
} }
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
void ModifyHealth::_Apply() { void ModifyHealth::_Apply() {
GameInteractor::RawAction::HealOrDamagePlayer(parameters[0]); GameInteractor::RawAction::HealOrDamagePlayer(parameters[0]);
} }
// MARK: - SetPlayerHealth // MARK: - SetPlayerHealth
GameInteractionEffectQueryResult SetPlayerHealth::CanBeApplied() { GameInteractionEffectQueryResult SetPlayerHealth::CanBeApplied() {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void SetPlayerHealth::_Apply() { void SetPlayerHealth::_Apply() {
GameInteractor::RawAction::SetPlayerHealth(parameters[0]); GameInteractor::RawAction::SetPlayerHealth(parameters[0]);
} }
// MARK: - FreezePlayer // MARK: - FreezePlayer
GameInteractionEffectQueryResult FreezePlayer::CanBeApplied() { GameInteractionEffectQueryResult FreezePlayer::CanBeApplied() {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void FreezePlayer::_Apply() { void FreezePlayer::_Apply() {
GameInteractor::RawAction::FreezePlayer(); GameInteractor::RawAction::FreezePlayer();
} }
// MARK: - BurnPlayer // MARK: - BurnPlayer
GameInteractionEffectQueryResult BurnPlayer::CanBeApplied() { GameInteractionEffectQueryResult BurnPlayer::CanBeApplied() {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void BurnPlayer::_Apply() { void BurnPlayer::_Apply() {
GameInteractor::RawAction::BurnPlayer(); GameInteractor::RawAction::BurnPlayer();
} }
// MARK: - ElectrocutePlayer // MARK: - ElectrocutePlayer
GameInteractionEffectQueryResult ElectrocutePlayer::CanBeApplied() { GameInteractionEffectQueryResult ElectrocutePlayer::CanBeApplied() {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void ElectrocutePlayer::_Apply() { void ElectrocutePlayer::_Apply() {
GameInteractor::RawAction::ElectrocutePlayer(); GameInteractor::RawAction::ElectrocutePlayer();
} }
// 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;
} }
} }
void KnockbackPlayer::_Apply() { void KnockbackPlayer::_Apply() {
GameInteractor::RawAction::KnockbackPlayer(parameters[0]); GameInteractor::RawAction::KnockbackPlayer(parameters[0]);
} }
// MARK: - ModifyLinkSize // MARK: - ModifyLinkSize
GameInteractionEffectQueryResult ModifyLinkSize::CanBeApplied() { GameInteractionEffectQueryResult ModifyLinkSize::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void ModifyLinkSize::_Apply() { void ModifyLinkSize::_Apply() {
GameInteractor::State::LinkSize = (GILinkSize)parameters[0]; GameInteractor::State::LinkSize = (GILinkSize)parameters[0];
} }
void ModifyLinkSize::_Remove() { void ModifyLinkSize::_Remove() {
GameInteractor::State::LinkSize = GI_LINK_SIZE_RESET; GameInteractor::State::LinkSize = GI_LINK_SIZE_RESET;
} }
// MARK: - InvisibleLink // MARK: - InvisibleLink
GameInteractionEffectQueryResult InvisibleLink::CanBeApplied() { GameInteractionEffectQueryResult InvisibleLink::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void InvisibleLink::_Apply() { void InvisibleLink::_Apply() {
GameInteractor::RawAction::SetLinkInvisibility(true); GameInteractor::RawAction::SetLinkInvisibility(true);
} }
void InvisibleLink::_Remove() { void InvisibleLink::_Remove() {
GameInteractor::RawAction::SetLinkInvisibility(false); GameInteractor::RawAction::SetLinkInvisibility(false);
} }
// MARK: - PacifistMode // MARK: - PacifistMode
GameInteractionEffectQueryResult PacifistMode::CanBeApplied() { GameInteractionEffectQueryResult PacifistMode::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void PacifistMode::_Apply() { void PacifistMode::_Apply() {
GameInteractor::State::SetPacifistMode(true); GameInteractor::State::SetPacifistMode(true);
} }
void PacifistMode::_Remove() { void PacifistMode::_Remove() {
GameInteractor::State::SetPacifistMode(false); GameInteractor::State::SetPacifistMode(false);
} }
// MARK: - DisableZTargeting // MARK: - DisableZTargeting
GameInteractionEffectQueryResult DisableZTargeting::CanBeApplied() { GameInteractionEffectQueryResult DisableZTargeting::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void DisableZTargeting::_Apply() { void DisableZTargeting::_Apply() {
GameInteractor::State::DisableZTargetingActive = 1; GameInteractor::State::DisableZTargetingActive = 1;
} }
void DisableZTargeting::_Remove() { void DisableZTargeting::_Remove() {
GameInteractor::State::DisableZTargetingActive = 0; GameInteractor::State::DisableZTargetingActive = 0;
} }
// MARK: - WeatherRainstorm // MARK: - WeatherRainstorm
GameInteractionEffectQueryResult WeatherRainstorm::CanBeApplied() { GameInteractionEffectQueryResult WeatherRainstorm::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void WeatherRainstorm::_Apply() { void WeatherRainstorm::_Apply() {
GameInteractor::RawAction::SetWeatherStorm(true); GameInteractor::RawAction::SetWeatherStorm(true);
} }
void WeatherRainstorm::_Remove() { void WeatherRainstorm::_Remove() {
GameInteractor::RawAction::SetWeatherStorm(false); GameInteractor::RawAction::SetWeatherStorm(false);
} }
// MARK: - ReverseControls // MARK: - ReverseControls
GameInteractionEffectQueryResult ReverseControls::CanBeApplied() { GameInteractionEffectQueryResult ReverseControls::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void ReverseControls::_Apply() { void ReverseControls::_Apply() {
GameInteractor::State::ReverseControlsActive = 1; GameInteractor::State::ReverseControlsActive = 1;
} }
void ReverseControls::_Remove() { void ReverseControls::_Remove() {
GameInteractor::State::ReverseControlsActive = 0; GameInteractor::State::ReverseControlsActive = 0;
} }
// MARK: - ForceEquipBoots // MARK: - ForceEquipBoots
GameInteractionEffectQueryResult ForceEquipBoots::CanBeApplied() { GameInteractionEffectQueryResult ForceEquipBoots::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void ForceEquipBoots::_Apply() { void ForceEquipBoots::_Apply() {
GameInteractor::RawAction::ForceEquipBoots(parameters[0]); GameInteractor::RawAction::ForceEquipBoots(parameters[0]);
} }
void ForceEquipBoots::_Remove() { void ForceEquipBoots::_Remove() {
GameInteractor::RawAction::ForceEquipBoots(EQUIP_VALUE_BOOTS_KOKIRI); GameInteractor::RawAction::ForceEquipBoots(EQUIP_VALUE_BOOTS_KOKIRI);
} }
// MARK: - ModifyRunSpeedModifier // MARK: - ModifyRunSpeedModifier
GameInteractionEffectQueryResult ModifyRunSpeedModifier::CanBeApplied() { GameInteractionEffectQueryResult ModifyRunSpeedModifier::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void ModifyRunSpeedModifier::_Apply() { void ModifyRunSpeedModifier::_Apply() {
GameInteractor::State::RunSpeedModifier = parameters[0]; GameInteractor::State::RunSpeedModifier = parameters[0];
} }
void ModifyRunSpeedModifier::_Remove() { void ModifyRunSpeedModifier::_Remove() {
GameInteractor::State::RunSpeedModifier = 0; GameInteractor::State::RunSpeedModifier = 0;
} }
// MARK: - OneHitKO // MARK: - OneHitKO
GameInteractionEffectQueryResult OneHitKO::CanBeApplied() { GameInteractionEffectQueryResult OneHitKO::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void OneHitKO::_Apply() { void OneHitKO::_Apply() {
GameInteractor::State::OneHitKOActive = 1; GameInteractor::State::OneHitKOActive = 1;
} }
void OneHitKO::_Remove() { void OneHitKO::_Remove() {
GameInteractor::State::OneHitKOActive = 0; GameInteractor::State::OneHitKOActive = 0;
} }
// MARK: - ModifyDefenseModifier // MARK: - ModifyDefenseModifier
GameInteractionEffectQueryResult ModifyDefenseModifier::CanBeApplied() { GameInteractionEffectQueryResult ModifyDefenseModifier::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void ModifyDefenseModifier::_Apply() { void ModifyDefenseModifier::_Apply() {
GameInteractor::State::DefenseModifier = parameters[0]; GameInteractor::State::DefenseModifier = parameters[0];
} }
void ModifyDefenseModifier::_Remove() { void ModifyDefenseModifier::_Remove() {
GameInteractor::State::DefenseModifier = 0; GameInteractor::State::DefenseModifier = 0;
} }
// MARK: - GiveOrTakeShield // MARK: - GiveOrTakeShield
GameInteractionEffectQueryResult GiveOrTakeShield::CanBeApplied() { GameInteractionEffectQueryResult GiveOrTakeShield::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
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 {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void GiveOrTakeShield::_Apply() { void GiveOrTakeShield::_Apply() {
GameInteractor::RawAction::GiveOrTakeShield(parameters[0]); GameInteractor::RawAction::GiveOrTakeShield(parameters[0]);
} }
// MARK: - TeleportPlayer // MARK: - TeleportPlayer
GameInteractionEffectQueryResult TeleportPlayer::CanBeApplied() { GameInteractionEffectQueryResult TeleportPlayer::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void TeleportPlayer::_Apply() { void TeleportPlayer::_Apply() {
GameInteractor::RawAction::TeleportPlayer(parameters[0]); GameInteractor::RawAction::TeleportPlayer(parameters[0]);
} }
// MARK: - ClearAssignedButtons // MARK: - ClearAssignedButtons
GameInteractionEffectQueryResult ClearAssignedButtons::CanBeApplied() { GameInteractionEffectQueryResult ClearAssignedButtons::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void ClearAssignedButtons::_Apply() { void ClearAssignedButtons::_Apply() {
GameInteractor::RawAction::ClearAssignedButtons(parameters[0]); GameInteractor::RawAction::ClearAssignedButtons(parameters[0]);
} }
// MARK: - SetTimeOfDay // MARK: - SetTimeOfDay
GameInteractionEffectQueryResult SetTimeOfDay::CanBeApplied() { GameInteractionEffectQueryResult SetTimeOfDay::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void SetTimeOfDay::_Apply() { void SetTimeOfDay::_Apply() {
GameInteractor::RawAction::SetTimeOfDay(parameters[0]); GameInteractor::RawAction::SetTimeOfDay(parameters[0]);
} }
// MARK: - SetCollisionViewer // MARK: - SetCollisionViewer
GameInteractionEffectQueryResult SetCollisionViewer::CanBeApplied() { GameInteractionEffectQueryResult SetCollisionViewer::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void SetCollisionViewer::_Apply() { void SetCollisionViewer::_Apply() {
GameInteractor::RawAction::SetCollisionViewer(true); GameInteractor::RawAction::SetCollisionViewer(true);
} }
void SetCollisionViewer::_Remove() { void SetCollisionViewer::_Remove() {
GameInteractor::RawAction::SetCollisionViewer(false); GameInteractor::RawAction::SetCollisionViewer(false);
} }
// MARK: - SetCosmeticsColor // MARK: - SetCosmeticsColor
GameInteractionEffectQueryResult SetCosmeticsColor::CanBeApplied() { GameInteractionEffectQueryResult SetCosmeticsColor::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void SetCosmeticsColor::_Apply() { void SetCosmeticsColor::_Apply() {
GameInteractor::RawAction::SetCosmeticsColor(parameters[0], parameters[1]); GameInteractor::RawAction::SetCosmeticsColor(parameters[0], parameters[1]);
} }
// MARK: - RandomizeCosmetics // MARK: - RandomizeCosmetics
GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() { GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void RandomizeCosmetics::_Apply() { void RandomizeCosmetics::_Apply() {
GameInteractor::RawAction::RandomizeCosmeticsColors(true); GameInteractor::RawAction::RandomizeCosmeticsColors(true);
} }
// MARK: - PressButton // MARK: - PressButton
GameInteractionEffectQueryResult PressButton::CanBeApplied() { GameInteractionEffectQueryResult PressButton::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void PressButton::_Apply() { void PressButton::_Apply() {
GameInteractor::RawAction::EmulateButtonPress(parameters[0]); GameInteractor::RawAction::EmulateButtonPress(parameters[0]);
} }
// MARK: - PressRandomButton // MARK: - PressRandomButton
GameInteractionEffectQueryResult PressRandomButton::CanBeApplied() { GameInteractionEffectQueryResult PressRandomButton::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void PressRandomButton::_Apply() { void PressRandomButton::_Apply() {
GameInteractor::RawAction::EmulateRandomButtonPress(parameters[0]); GameInteractor::RawAction::EmulateRandomButtonPress(parameters[0]);
} }
// MARK: - AddOrTakeAmmo // MARK: - AddOrTakeAmmo
GameInteractionEffectQueryResult AddOrTakeAmmo::CanBeApplied() { GameInteractionEffectQueryResult AddOrTakeAmmo::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else if (!GameInteractor::CanAddOrTakeAmmo(parameters[0], parameters[1])) { } else if (!GameInteractor::CanAddOrTakeAmmo(parameters[0], parameters[1])) {
@ -546,122 +542,122 @@ namespace GameInteractionEffect {
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void AddOrTakeAmmo::_Apply() { void AddOrTakeAmmo::_Apply() {
GameInteractor::RawAction::AddOrTakeAmmo(parameters[0], parameters[1]); GameInteractor::RawAction::AddOrTakeAmmo(parameters[0], parameters[1]);
} }
// MARK: - RandomBombFuseTimer // MARK: - RandomBombFuseTimer
GameInteractionEffectQueryResult RandomBombFuseTimer::CanBeApplied() { GameInteractionEffectQueryResult RandomBombFuseTimer::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void RandomBombFuseTimer::_Apply() { void RandomBombFuseTimer::_Apply() {
GameInteractor::State::RandomBombFuseTimerActive = 1; GameInteractor::State::RandomBombFuseTimerActive = 1;
} }
void RandomBombFuseTimer::_Remove() { void RandomBombFuseTimer::_Remove() {
GameInteractor::State::RandomBombFuseTimerActive = 0; GameInteractor::State::RandomBombFuseTimerActive = 0;
} }
// MARK: - DisableLedgeGrabs // MARK: - DisableLedgeGrabs
GameInteractionEffectQueryResult DisableLedgeGrabs::CanBeApplied() { GameInteractionEffectQueryResult DisableLedgeGrabs::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void DisableLedgeGrabs::_Apply() { void DisableLedgeGrabs::_Apply() {
GameInteractor::State::DisableLedgeGrabsActive = 1; GameInteractor::State::DisableLedgeGrabsActive = 1;
} }
void DisableLedgeGrabs::_Remove() { void DisableLedgeGrabs::_Remove() {
GameInteractor::State::DisableLedgeGrabsActive = 0; GameInteractor::State::DisableLedgeGrabsActive = 0;
} }
// MARK: - RandomWind // MARK: - RandomWind
GameInteractionEffectQueryResult RandomWind::CanBeApplied() { GameInteractionEffectQueryResult RandomWind::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void RandomWind::_Apply() { void RandomWind::_Apply() {
GameInteractor::RawAction::SetRandomWind(true); GameInteractor::RawAction::SetRandomWind(true);
} }
void RandomWind::_Remove() { void RandomWind::_Remove() {
GameInteractor::RawAction::SetRandomWind(false); GameInteractor::RawAction::SetRandomWind(false);
} }
// MARK: - RandomBonks // MARK: - RandomBonks
GameInteractionEffectQueryResult RandomBonks::CanBeApplied() { GameInteractionEffectQueryResult RandomBonks::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void RandomBonks::_Apply() { void RandomBonks::_Apply() {
GameInteractor::State::RandomBonksActive = 1; GameInteractor::State::RandomBonksActive = 1;
} }
void RandomBonks::_Remove() { void RandomBonks::_Remove() {
GameInteractor::State::RandomBonksActive = 0; GameInteractor::State::RandomBonksActive = 0;
} }
// MARK: - PlayerInvincibility // MARK: - PlayerInvincibility
GameInteractionEffectQueryResult PlayerInvincibility::CanBeApplied() { GameInteractionEffectQueryResult PlayerInvincibility::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void PlayerInvincibility::_Apply() { void PlayerInvincibility::_Apply() {
GameInteractor::RawAction::SetPlayerInvincibility(true); GameInteractor::RawAction::SetPlayerInvincibility(true);
} }
void PlayerInvincibility::_Remove() { void PlayerInvincibility::_Remove() {
GameInteractor::RawAction::SetPlayerInvincibility(false); GameInteractor::RawAction::SetPlayerInvincibility(false);
} }
// MARK: - SlipperyFloor // MARK: - SlipperyFloor
GameInteractionEffectQueryResult SlipperyFloor::CanBeApplied() { GameInteractionEffectQueryResult SlipperyFloor::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} else { } else {
return GameInteractionEffectQueryResult::Possible; return GameInteractionEffectQueryResult::Possible;
} }
} }
void SlipperyFloor::_Apply() { void SlipperyFloor::_Apply() {
GameInteractor::State::SlipperyFloorActive = 1; GameInteractor::State::SlipperyFloorActive = 1;
} }
void SlipperyFloor::_Remove() { void SlipperyFloor::_Remove() {
GameInteractor::State::SlipperyFloorActive = 0; GameInteractor::State::SlipperyFloorActive = 0;
} }
// MARK: - SpawnEnemyWithOffset // MARK: - SpawnEnemyWithOffset
GameInteractionEffectQueryResult SpawnEnemyWithOffset::CanBeApplied() { GameInteractionEffectQueryResult SpawnEnemyWithOffset::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
return GameInteractor::RawAction::SpawnEnemyWithOffset(parameters[0], parameters[1]); return GameInteractor::RawAction::SpawnEnemyWithOffset(parameters[0], parameters[1]);
} }
void SpawnEnemyWithOffset::_Apply() { void SpawnEnemyWithOffset::_Apply() {
GameInteractor::RawAction::SpawnEnemyWithOffset(parameters[0], parameters[1]); GameInteractor::RawAction::SpawnEnemyWithOffset(parameters[0], parameters[1]);
} }
// MARK: - SpawnActor // MARK: - SpawnActor
GameInteractionEffectQueryResult SpawnActor::CanBeApplied() { GameInteractionEffectQueryResult SpawnActor::CanBeApplied() {
if (!GameInteractor::IsSaveLoaded()) { if (!GameInteractor::IsSaveLoaded()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible; return GameInteractionEffectQueryResult::TemporarilyNotPossible;
} }
return GameInteractor::RawAction::SpawnActor(parameters[0], parameters[1]); return GameInteractor::RawAction::SpawnActor(parameters[0], parameters[1]);
}
void SpawnActor::_Apply() {
GameInteractor::RawAction::SpawnActor(parameters[0], parameters[1]);
}
} }
void SpawnActor::_Apply() {
GameInteractor::RawAction::SpawnActor(parameters[0], parameters[1]);
}
} // namespace GameInteractionEffect

View file

@ -6,271 +6,269 @@
#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;
}; };
class RemovableGameInteractionEffect: public GameInteractionEffectBase { class RemovableGameInteractionEffect : public GameInteractionEffectBase {
public: public:
virtual GameInteractionEffectQueryResult CanBeRemoved(); virtual GameInteractionEffectQueryResult CanBeRemoved();
GameInteractionEffectQueryResult Remove(); GameInteractionEffectQueryResult Remove();
protected:
virtual void _Remove() {}; protected:
virtual void _Remove(){};
}; };
class ParameterizedGameInteractionEffect { class ParameterizedGameInteractionEffect {
public: public:
int32_t parameters[3]; int32_t parameters[3];
}; };
namespace GameInteractionEffect { namespace GameInteractionEffect {
class SetSceneFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SetSceneFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class UnsetSceneFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class UnsetSceneFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class SetFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SetFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class UnsetFlag: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class UnsetFlag : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class ModifyHeartContainers: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class ModifyHeartContainers : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class FillMagic: public GameInteractionEffectBase { class FillMagic : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class EmptyMagic: public GameInteractionEffectBase { class EmptyMagic : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class ModifyRupees: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class ModifyRupees : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class NoUI: public RemovableGameInteractionEffect { class NoUI : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ModifyGravity: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ModifyGravity : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ModifyHealth: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class ModifyHealth : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class SetPlayerHealth: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SetPlayerHealth : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class FreezePlayer: public GameInteractionEffectBase { class FreezePlayer : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class BurnPlayer: public GameInteractionEffectBase { class BurnPlayer : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class ElectrocutePlayer: public GameInteractionEffectBase { class ElectrocutePlayer : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class KnockbackPlayer: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class KnockbackPlayer : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class ModifyLinkSize: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ModifyLinkSize : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class InvisibleLink : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class InvisibleLink : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class PacifistMode : public RemovableGameInteractionEffect { class PacifistMode : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class DisableZTargeting: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class DisableZTargeting : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class WeatherRainstorm: public RemovableGameInteractionEffect { class WeatherRainstorm : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ReverseControls: public RemovableGameInteractionEffect { class ReverseControls : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ForceEquipBoots: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ForceEquipBoots : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ModifyRunSpeedModifier: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ModifyRunSpeedModifier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class OneHitKO : public RemovableGameInteractionEffect { class OneHitKO : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class ModifyDefenseModifier: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class ModifyDefenseModifier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class GiveOrTakeShield: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class GiveOrTakeShield : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class TeleportPlayer: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class TeleportPlayer : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class ClearAssignedButtons: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class ClearAssignedButtons : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class SetTimeOfDay: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SetTimeOfDay : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class SetCollisionViewer: public RemovableGameInteractionEffect { class SetCollisionViewer : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class SetCosmeticsColor: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SetCosmeticsColor : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class RandomizeCosmetics: public GameInteractionEffectBase { class RandomizeCosmetics : public GameInteractionEffectBase {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class PressButton: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class PressButton : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class PressRandomButton: public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { class PressRandomButton : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class AddOrTakeAmmo: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class AddOrTakeAmmo : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class RandomBombFuseTimer: public RemovableGameInteractionEffect { class RandomBombFuseTimer : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class DisableLedgeGrabs: public RemovableGameInteractionEffect { class DisableLedgeGrabs : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class RandomWind: public RemovableGameInteractionEffect { class RandomWind : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class RandomBonks: public RemovableGameInteractionEffect { class RandomBonks : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class PlayerInvincibility: public RemovableGameInteractionEffect { class PlayerInvincibility : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class SlipperyFloor: public RemovableGameInteractionEffect { class SlipperyFloor : public RemovableGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
void _Remove() override; void _Remove() override;
}; };
class SpawnEnemyWithOffset: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SpawnEnemyWithOffset : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
GameInteractionEffectQueryResult CanBeApplied() override; GameInteractionEffectQueryResult CanBeApplied() override;
void _Apply() override; void _Apply() override;
}; };
class SpawnActor: public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { class SpawnActor : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect {
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

@ -34,9 +34,9 @@ DEFINE_HOOK(OnPlayerBonk, ());
DEFINE_HOOK(OnPlayerHealthChange, (int16_t amount)); DEFINE_HOOK(OnPlayerHealthChange, (int16_t amount));
DEFINE_HOOK(OnPlayerBottleUpdate, (int16_t contents)); DEFINE_HOOK(OnPlayerBottleUpdate, (int16_t contents));
DEFINE_HOOK(OnPlayerHoldUpShield, ()); DEFINE_HOOK(OnPlayerHoldUpShield, ());
DEFINE_HOOK(OnPlayerFirstPersonControl, (Player* player)); DEFINE_HOOK(OnPlayerFirstPersonControl, (Player * player));
DEFINE_HOOK(OnPlayerProcessStick, ()); DEFINE_HOOK(OnPlayerProcessStick, ());
DEFINE_HOOK(OnPlayerShieldControl, (float_t* sp50, float_t* sp54)); DEFINE_HOOK(OnPlayerShieldControl, (float_t * sp50, float_t* sp54));
DEFINE_HOOK(OnPlayDestroy, ()); DEFINE_HOOK(OnPlayDestroy, ());
DEFINE_HOOK(OnPlayDrawEnd, ()); DEFINE_HOOK(OnPlayDrawEnd, ());
DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list originalArgs)); DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list originalArgs));

View file

@ -126,7 +126,7 @@ void GameInteractor_ExecuteOnBossDefeat(void* actor) {
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnBossDefeat>(actor); GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnBossDefeat>(actor);
} }
void GameInteractor_ExecuteOnTimestamp (u8 item) { void GameInteractor_ExecuteOnTimestamp(u8 item) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnTimestamp>(item); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnTimestamp>(item);
} }
@ -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) {
@ -285,7 +286,7 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)) {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnAssetAltChange>(fn); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnAssetAltChange>(fn);
} }
//MARK: Pause Menu // MARK: Pause Menu
void GameInteractor_ExecuteOnKaleidoUpdate() { void GameInteractor_ExecuteOnKaleidoUpdate() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnKaleidoUpdate>(); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnKaleidoUpdate>();

View file

@ -31,7 +31,7 @@ void GameInteractor_ExecuteOnActorUpdate(void* actor);
void GameInteractor_ExecuteOnActorKill(void* actor); void GameInteractor_ExecuteOnActorKill(void* actor);
void GameInteractor_ExecuteOnEnemyDefeat(void* actor); void GameInteractor_ExecuteOnEnemyDefeat(void* actor);
void GameInteractor_ExecuteOnBossDefeat(void* actor); void GameInteractor_ExecuteOnBossDefeat(void* actor);
void GameInteractor_ExecuteOnTimestamp (u8 item); void GameInteractor_ExecuteOnTimestamp(u8 item);
void GameInteractor_ExecuteOnPlayerBonk(); void GameInteractor_ExecuteOnPlayerBonk();
void GameInteractor_ExecuteOnPlayerHealthChange(int16_t amount); void GameInteractor_ExecuteOnPlayerHealthChange(int16_t amount);
void GameInteractor_ExecuteOnPlayerBottleUpdate(int16_t contents); void GameInteractor_ExecuteOnPlayerBottleUpdate(int16_t contents);
@ -76,7 +76,7 @@ void GameInteractor_ExecuteOnSetGameLanguage();
// MARK: - System // MARK: - System
void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)); void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void));
//Mark: - Pause Menu // Mark: - Pause Menu
void GameInteractor_ExecuteOnKaleidoUpdate(); void GameInteractor_ExecuteOnKaleidoUpdate();
#ifdef __cplusplus #ifdef __cplusplus

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)
static uint32_t null_cs[] = {0, 0}; return;
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,22 +8,19 @@
#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,
CONSOLECOMMAND_RESULT_FAILURE CONSOLECOMMAND_RESULT_FAILURE
} ConsoleCommandResult; } ConsoleCommandResult;
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

@ -124,7 +124,7 @@ const char* const sceneMappings[] = {
"Goron City", "Goron City",
"Lon Lon Ranch", "Lon Lon Ranch",
"Outside Ganon's Castle", "Outside Ganon's Castle",
//Debug Rooms // Debug Rooms
"Test Map", "Test Map",
"Test Room", "Test Room",
"Depth Test", "Depth Test",
@ -248,14 +248,14 @@ typedef struct {
u32 time; u32 time;
ImVec4 color; ImVec4 color;
bool isRoom; bool isRoom;
}TimestampInfo; } TimestampInfo;
// Timestamps are an array of structs, each with a name, time, and color // Timestamps are an array of structs, each with a name, time, and color
// Names and colors are set up at the bottom of this file. // Names and colors are set up at the bottom of this file.
// Times are stored in gSaveContext.ship.stats.itemTimestamp. // Times are stored in gSaveContext.ship.stats.itemTimestamp.
TimestampInfo itemTimestampDisplay[TIMESTAMP_MAX]; TimestampInfo itemTimestampDisplay[TIMESTAMP_MAX];
TimestampInfo sceneTimestampDisplay[8191]; TimestampInfo sceneTimestampDisplay[8191];
//std::vector<TimestampInfo> sceneTimestampDisplay; // std::vector<TimestampInfo> sceneTimestampDisplay;
std::string formatTimestampGameplayStat(uint32_t value) { std::string formatTimestampGameplayStat(uint32_t value) {
uint32_t sec = value / 10; uint32_t sec = value / 10;
@ -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,
@ -391,10 +394,10 @@ void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color
} }
bool compareTimestampInfoByTime(const TimestampInfo& a, const TimestampInfo& b) { bool compareTimestampInfoByTime(const TimestampInfo& a, const TimestampInfo& b) {
return CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.ReverseTimestamps"), 0) ? a.time > b.time : a.time < b.time; return CVarGetInteger(CVAR_GAMEPLAY_STATS("ReverseTimestamps"), 0) ? a.time > b.time : a.time < b.time;
} }
const char* ResolveSceneID(int sceneID, int roomID){ const char* ResolveSceneID(int sceneID, int roomID) {
if (sceneID == SCENE_GROTTOS) { if (sceneID == SCENE_GROTTOS) {
switch (roomID) { switch (roomID) {
case 0: case 0:
@ -427,7 +430,7 @@ const char* ResolveSceneID(int sceneID, int roomID){
return "Big Skulltula Grotto"; return "Big Skulltula Grotto";
}; };
} else if (sceneID == SCENE_WINDMILL_AND_DAMPES_GRAVE) { } else if (sceneID == SCENE_WINDMILL_AND_DAMPES_GRAVE) {
//Only the last room of Dampe's Grave (rm 6) is considered the windmill. // Only the last room of Dampe's Grave (rm 6) is considered the windmill.
return roomID == 6 ? "Windmill" : "Dampe's Grave"; return roomID == 6 ? "Windmill" : "Dampe's Grave";
} else if (sceneID < SCENE_ID_MAX) { } else if (sceneID < SCENE_ID_MAX) {
return sceneMappings[sceneID]; return sceneMappings[sceneID];
@ -440,7 +443,7 @@ void DrawGameplayStatsHeader() {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 4.0f, 4.0f }); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 4.0f, 4.0f });
ImGui::BeginTable("gameplayStatsHeader", 1, ImGuiTableFlags_BordersOuter); ImGui::BeginTable("gameplayStatsHeader", 1, ImGuiTableFlags_BordersOuter);
ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch);
//if tag is empty (not a release build) // if tag is empty (not a release build)
if (gGitCommitTag[0] == 0) { if (gGitCommitTag[0] == 0) {
GameplayStatsRow("Git Branch:", (char*)gGitBranch); GameplayStatsRow("Git Branch:", (char*)gGitBranch);
GameplayStatsRow("Git Commit Hash:", (char*)gGitCommitHash); GameplayStatsRow("Git Commit Hash:", (char*)gGitCommitHash);
@ -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_ENHANCEMENT("GameplayStats.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_ENHANCEMENT("GameplayStats.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_ENHANCEMENT("GameplayStats.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_ENHANCEMENT("GameplayStats.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;
} }
@ -593,14 +613,16 @@ void DrawGameplayStatsBreakdownTab() {
ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch);
for (int i = 0; i < gSaveContext.ship.stats.tsIdx; i++) { for (int i = 0; i < gSaveContext.ship.stats.tsIdx; i++) {
TimestampInfo tsInfo = sceneTimestampDisplay[i]; TimestampInfo tsInfo = sceneTimestampDisplay[i];
bool canShow = !tsInfo.isRoom || CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0); bool canShow = !tsInfo.isRoom || CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0);
if (tsInfo.time > 0 && strnlen(tsInfo.name, 40) > 1 && canShow) { if (tsInfo.time > 0 && strnlen(tsInfo.name, 40) > 1 && canShow) {
GameplayStatsRow(tsInfo.name, formatTimestampGameplayStat(tsInfo.time), tsInfo.color); GameplayStatsRow(tsInfo.name, formatTimestampGameplayStat(tsInfo.time), tsInfo.color);
} }
} }
std::string toPass; std::string toPass;
if (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.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);
} }
@ -610,27 +632,27 @@ void DrawGameplayStatsBreakdownTab() {
} }
void DrawGameplayStatsOptionsTab() { void DrawGameplayStatsOptionsTab() {
UIWidgets::CVarCheckbox("Show in-game total timer", CVAR_ENHANCEMENT("GameplayStats.ShowIngameTimer"), UIWidgets::CVarCheckbox("Show in-game total timer", CVAR_GAMEPLAY_STATS("ShowIngameTimer"),
UIWidgets::CheckboxOptions() UIWidgets::CheckboxOptions()
.Tooltip("Keep track of the timer as an in-game HUD element. The position of the " .Tooltip("Keep track of the timer as an in-game HUD element. The position of the "
"timer can be changed in the Cosmetics Editor.") "timer can be changed in the Cosmetics Editor.")
.Color(THEME_COLOR)); .Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show latest timestamps on top", CVAR_ENHANCEMENT("GameplayStats.ReverseTimestamps"), UIWidgets::CVarCheckbox("Show latest timestamps on top", CVAR_GAMEPLAY_STATS("ReverseTimestamps"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR)); UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Room Breakdown", CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), UIWidgets::CVarCheckbox("Room Breakdown", CVAR_GAMEPLAY_STATS("RoomBreakdown"),
UIWidgets::CheckboxOptions() UIWidgets::CheckboxOptions()
.Tooltip("Allows a more in-depth perspective of time spent in a certain map.") .Tooltip("Allows a more in-depth perspective of time spent in a certain map.")
.Color(THEME_COLOR)); .Color(THEME_COLOR));
UIWidgets::CVarCheckbox("RTA Timing on new files", CVAR_ENHANCEMENT("GameplayStats.RTATiming"), UIWidgets::CVarCheckbox("RTA Timing on new files", CVAR_GAMEPLAY_STATS("RTATiming"),
UIWidgets::CheckboxOptions() UIWidgets::CheckboxOptions()
.Tooltip("Timestamps are relative to starting timestamp rather than in game time, " .Tooltip("Timestamps are relative to starting timestamp rather than in game time, "
"usually necessary for races/speedruns.\n\n" "usually necessary for races/speedruns.\n\n"
"Starting timestamp is on first non-C-up input after intro cutscene.\n\n" "Starting timestamp is on first non-C-up input after intro cutscene.\n\n"
"NOTE: THIS NEEDS TO BE SET BEFORE CREATING A FILE TO TAKE EFFECT") "NOTE: THIS NEEDS TO BE SET BEFORE CREATING A FILE TO TAKE EFFECT")
.Color(THEME_COLOR)); .Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show additional detail timers", CVAR_ENHANCEMENT("GameplayStats.ShowAdditionalTimers"), UIWidgets::CVarCheckbox("Show additional detail timers", CVAR_GAMEPLAY_STATS("ShowAdditionalTimers"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR)); UIWidgets::CheckboxOptions().Color(THEME_COLOR));
UIWidgets::CVarCheckbox("Show Debug Info", CVAR_ENHANCEMENT("GameplayStats.ShowDebugInfo"), UIWidgets::CVarCheckbox("Show Debug Info", CVAR_GAMEPLAY_STATS("ShowDebugInfo"),
UIWidgets::CheckboxOptions().Color(THEME_COLOR)); UIWidgets::CheckboxOptions().Color(THEME_COLOR));
} }
@ -671,7 +693,7 @@ void InitStats(bool isDebug) {
for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.ship.stats.dungeonKeys); dungeon++) { for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.ship.stats.dungeonKeys); dungeon++) {
gSaveContext.ship.stats.dungeonKeys[dungeon] = isDebug ? 8 : 0; gSaveContext.ship.stats.dungeonKeys[dungeon] = isDebug ? 8 : 0;
} }
gSaveContext.ship.stats.rtaTiming = CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RTATiming"), 0); gSaveContext.ship.stats.rtaTiming = CVarGetInteger(CVAR_GAMEPLAY_STATS("RTATiming"), 0);
gSaveContext.ship.stats.fileCreatedAt = 0; gSaveContext.ship.stats.fileCreatedAt = 0;
gSaveContext.ship.stats.playTimer = 0; gSaveContext.ship.stats.playTimer = 0;
gSaveContext.ship.stats.pauseTimer = 0; gSaveContext.ship.stats.pauseTimer = 0;
@ -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

@ -6,30 +6,32 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
uint64_t GetUnixTimestamp(void); uint64_t GetUnixTimestamp(void);
char* GameplayStats_GetCurrentTime(); char* GameplayStats_GetCurrentTime();
#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif #endif
// When using RTA timing // When using RTA timing
// get the diff since the save was created, // get the diff since the save was created,
// unless the game is complete in which we use the defeated ganon timestamp // unless the game is complete in which we use the defeated ganon timestamp
// When not using RTA timing // When not using RTA timing
// 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_ENHANCEMENT("GameplayStats.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();
@ -52,7 +54,7 @@ typedef enum {
/* 0xAA */ TIMESTAMP_TRIFORCE_COMPLETED, // z_parameter.c /* 0xAA */ TIMESTAMP_TRIFORCE_COMPLETED, // z_parameter.c
/* 0xAB */ TIMESTAMP_MAX /* 0xAB */ TIMESTAMP_MAX
}GameplayStatTimestamp; } GameplayStatTimestamp;
typedef enum { typedef enum {
// Enemies defeated // Enemies defeated

View file

@ -6,5 +6,5 @@ class GameplayStatsWindow : public Ship::GuiWindow {
void InitElement() override; void InitElement() override;
void DrawElement() override; void DrawElement() override;
void UpdateElement() override {}; void UpdateElement() override{};
}; };

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

@ -27,35 +27,35 @@ void KaleidoScope_MoveCursorToSpecialPos(PlayState* play, u16 specialPos);
namespace Rando { 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));
} }
} }
} }
KaleidoEntry::KaleidoEntry(int16_t x, int16_t y, std::string text) : mX(x), mY(y), mText(std::move(text)) { KaleidoEntry::KaleidoEntry(int16_t x, int16_t y, std::string text) : mX(x), mY(y), mText(std::move(text)) {
mHeight = 0; mHeight = 0;
mWidth = 0; mWidth = 0;
vtx = nullptr; vtx = nullptr;
} }
void KaleidoEntry::SetYOffset(int yOffset) { void KaleidoEntry::SetYOffset(int yOffset) {
mY = yOffset; mY = yOffset;
} }
void KaleidoEntryIcon::Draw(PlayState* play, std::vector<Gfx>* mEntryDl) { void KaleidoEntryIcon::Draw(PlayState* play, std::vector<Gfx>* mEntryDl) {
if (vtx == nullptr) { if (vtx == nullptr) {
return; return;
} }
@ -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,27 +100,26 @@ 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));
} }
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,42 +130,30 @@ 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;
} }
} }
extern "C" { extern "C" {
void FrameInterpolation_RecordCloseChild(void); void FrameInterpolation_RecordCloseChild(void);
void FrameInterpolation_RecordOpenChild(const void* a, int b); void FrameInterpolation_RecordOpenChild(const void* a, int b);
} }
void Kaleido::Draw(PlayState* play) { void Kaleido::Draw(PlayState* play) {
if (play == nullptr || mEntries.empty()) { if (play == nullptr || mEntries.empty()) {
return; return;
} }
@ -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);
@ -239,48 +230,49 @@ namespace Rando {
mEntryDl.push_back(gsSPEndDisplayList()); mEntryDl.push_back(gsSPEndDisplayList());
gSPDisplayList(POLY_OPA_DISP++, mEntryDl.data()); gSPDisplayList(POLY_OPA_DISP++, mEntryDl.data());
CLOSE_DISPS(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);
} }
void Kaleido::Update(PlayState *play) { void Kaleido::Update(PlayState* play) {
for(int i = mTopIndex; i < (mTopIndex + mNumVisible) && i < mEntries.size(); i++) { for (int i = mTopIndex; i < (mTopIndex + mNumVisible) && i < mEntries.size(); i++) {
const auto& entry = mEntries[i]; const auto& entry = mEntries[i];
entry->Update(play); entry->Update(play);
} }
} }
extern "C" void RandoKaleido_DrawMiscCollectibles(PlayState* play) { extern "C" void RandoKaleido_DrawMiscCollectibles(PlayState* play) {
OTRGlobals::Instance->gRandoContext->GetKaleido()->Draw(play); OTRGlobals::Instance->gRandoContext->GetKaleido()->Draw(play);
} }
extern "C" void RandoKaleido_UpdateMiscCollectibles(int16_t inDungeonScene) { extern "C" void RandoKaleido_UpdateMiscCollectibles(int16_t inDungeonScene) {
PauseContext* pauseCtx = &gPlayState->pauseCtx; PauseContext* pauseCtx = &gPlayState->pauseCtx;
if (pauseCtx->randoQuestMode && pauseCtx->pageIndex == PAUSE_QUEST) { if (pauseCtx->randoQuestMode && pauseCtx->pageIndex == PAUSE_QUEST) {
OTRGlobals::Instance->gRandoContext->GetKaleido()->Update(gPlayState); OTRGlobals::Instance->gRandoContext->GetKaleido()->Update(gPlayState);
} }
} }
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();
} }
void KaleidoEntryIconFlag::Update(PlayState* play) { void KaleidoEntryIconFlag::Update(PlayState* play) {
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();
BuildVertices(); BuildVertices();
} }
void KaleidoEntryIconCountRequired::BuildText() { void KaleidoEntryIconCountRequired::BuildText() {
std::ostringstream totals; std::ostringstream totals;
totals << mCount; totals << mCount;
if (mRequired != 0 && mCount < mRequired) { if (mRequired != 0 && mCount < mRequired) {
@ -290,9 +282,9 @@ namespace Rando {
totals << '/' << mTotal; totals << '/' << mTotal;
} }
mText = totals.str(); mText = totals.str();
} }
void KaleidoEntryIcon::BuildVertices() { void KaleidoEntryIcon::BuildVertices() {
int offsetY = 0; int offsetY = 0;
int offsetX = 0; int offsetX = 0;
// 4 vertices per character, plus one for the preceding icon. // 4 vertices per character, plus one for the preceding icon.
@ -314,43 +306,42 @@ namespace Rando {
vertices[3].v.ob[0] = 16; vertices[3].v.ob[0] = 16;
vertices[3].v.ob[1] = 16; vertices[3].v.ob[1] = 16;
vtx = vertices; vtx = vertices;
} }
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);
vtx = nullptr; vtx = nullptr;
BuildVertices(); BuildVertices();
} }
void KaleidoEntryIconCountRequired::Update(PlayState *play) { void KaleidoEntryIconCountRequired::Update(PlayState* play) {
if (mCount != *mWatch) { if (mCount != *mWatch) {
mCount = *mWatch; mCount = *mWatch;
BuildText(); BuildText();
RebuildVertices(); RebuildVertices();
mAchieved = mCount >= mRequired; mAchieved = mCount >= mRequired;
} }
}
} KaleidoEntryOcarinaButtons::KaleidoEntryOcarinaButtons(int16_t x, int16_t y)
: KaleidoEntryIcon(gItemIconOcarinaOfTimeTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32,
KaleidoEntryOcarinaButtons::KaleidoEntryOcarinaButtons(int16_t x, int16_t y) :
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();
} }
void KaleidoEntryOcarinaButtons::CalculateColors() { void KaleidoEntryOcarinaButtons::CalculateColors() {
Color_RGB8 aButtonColor = { 80, 150, 255 }; Color_RGB8 aButtonColor = { 80, 150, 255 };
if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) { if (CVarGetInteger(CVAR_COSMETIC("HUD.AButton.Changed"), 0)) {
aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor); aButtonColor = CVarGetColor24(CVAR_COSMETIC("HUD.AButton.Value"), aButtonColor);
} else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { } else if (CVarGetInteger(CVAR_COSMETIC("DefaultColorScheme"), COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) {
aButtonColor = { 80, 255, 150}; aButtonColor = { 80, 255, 150 };
} }
mButtonColors[0] = { aButtonColor.r, aButtonColor.g, aButtonColor.b, 255 }; mButtonColors[0] = { aButtonColor.r, aButtonColor.g, aButtonColor.b, 255 };
Color_RGB8 cButtonsColor = { 255, 255, 50 }; Color_RGB8 cButtonsColor = { 255, 255, 50 };
@ -380,9 +371,9 @@ namespace Rando {
mButtonColors[2] = { cDownButtonColor.r, cDownButtonColor.g, cDownButtonColor.b, 255 }; mButtonColors[2] = { cDownButtonColor.r, cDownButtonColor.g, cDownButtonColor.b, 255 };
mButtonColors[3] = { cLeftButtonColor.r, cLeftButtonColor.g, cLeftButtonColor.b, 255 }; mButtonColors[3] = { cLeftButtonColor.r, cLeftButtonColor.g, cLeftButtonColor.b, 255 };
mButtonColors[4] = { cRightButtonColor.r, cRightButtonColor.g, cRightButtonColor.b, 255 }; mButtonColors[4] = { cRightButtonColor.r, cRightButtonColor.g, cRightButtonColor.b, 255 };
} }
void KaleidoEntryOcarinaButtons::Update(PlayState *play) { void KaleidoEntryOcarinaButtons::Update(PlayState* play) {
mButtonCollected[0] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_A) > 0; mButtonCollected[0] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_A) > 0;
mButtonCollected[1] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_UP) > 0; mButtonCollected[1] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_UP) > 0;
mButtonCollected[2] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_DOWN) > 0; mButtonCollected[2] = GameInteractor::RawAction::CheckFlag(FLAG_RANDOMIZER_INF, RAND_INF_HAS_OCARINA_C_DOWN) > 0;
@ -397,9 +388,9 @@ namespace Rando {
mAchieved = true; mAchieved = true;
} }
} }
} }
void KaleidoEntryOcarinaButtons::Draw(PlayState *play, std::vector<Gfx>* mEntryDl) { void KaleidoEntryOcarinaButtons::Draw(PlayState* play, std::vector<Gfx>* mEntryDl) {
if (vtx == nullptr) { if (vtx == nullptr) {
return; return;
} }
@ -409,9 +400,10 @@ 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>
@ -18,7 +17,7 @@ namespace Rando {
* subclasses to declare their Draw and Update functions. * subclasses to declare their Draw and Update functions.
*/ */
class KaleidoEntry { class KaleidoEntry {
public: public:
/** /**
* @brief Constructor for Base KaleidoEntry class. Sets the position and * @brief Constructor for Base KaleidoEntry class. Sets the position and
* initial value of the line of text. * initial value of the line of text.
@ -31,7 +30,8 @@ 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;
int16_t mHeight; int16_t mHeight;
@ -39,7 +39,6 @@ protected:
Vtx* vtx; Vtx* vtx;
std::string mText; std::string mText;
bool mAchieved = false; bool mAchieved = false;
}; };
/** /**
@ -47,7 +46,7 @@ protected:
* that wish to render an Icon at the start of their line. * that wish to render an Icon at the start of their line.
*/ */
class KaleidoEntryIcon : public KaleidoEntry { class KaleidoEntryIcon : public KaleidoEntry {
public: public:
/** /**
* @param iconResourceName resource name of the icon to draw * @param iconResourceName resource name of the icon to draw
* @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA) * @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA)
@ -63,7 +62,8 @@ 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;
int mIconSize; int mIconSize;
@ -80,7 +80,7 @@ protected:
* that is either colored in or Grayscale according to a flag * that is either colored in or Grayscale according to a flag
*/ */
class KaleidoEntryIconFlag : public KaleidoEntryIcon { class KaleidoEntryIconFlag : public KaleidoEntryIcon {
public : public:
/** /**
* @param iconResourceName resource name of the icon to draw * @param iconResourceName resource name of the icon to draw
* @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA) * @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA)
@ -98,7 +98,8 @@ 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;
}; };
@ -109,7 +110,7 @@ private:
* render the count and not show progress towards a required amount or a total. * render the count and not show progress towards a required amount or a total.
*/ */
class KaleidoEntryIconCountRequired : public KaleidoEntryIcon { class KaleidoEntryIconCountRequired : public KaleidoEntryIcon {
public: public:
/** /**
* @param iconResourceName resource name of the icon to draw * @param iconResourceName resource name of the icon to draw
* @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA) * @param iconFormat flag representing the format of the icon (i.e. G_IM_FMT_IA)
@ -126,10 +127,12 @@ 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;
int mTotal; int mTotal;
@ -139,11 +142,12 @@ private:
}; };
class KaleidoEntryOcarinaButtons : public KaleidoEntryIcon { class KaleidoEntryOcarinaButtons : public KaleidoEntryIcon {
public: 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();
std::array<Color_RGBA8, 5> mButtonColors = {}; std::array<Color_RGBA8, 5> mButtonColors = {};
@ -151,17 +155,18 @@ private:
}; };
class Kaleido { class Kaleido {
public: 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() {
@ -549,11 +576,11 @@ void RegisterResetNaviTimer() {
}); });
} }
//this map is used for enemies that can be uniquely identified by their id // this map is used for enemies that can be uniquely identified by their id
//and that are always counted // and that are always counted
//enemies that can't be uniquely identified by their id // enemies that can't be uniquely identified by their id
//or only sometimes count (like ACTOR_EN_TP) // or only sometimes count (like ACTOR_EN_TP)
//have to be manually handled in RegisterEnemyDefeatCounts // have to be manually handled in RegisterEnemyDefeatCounts
static std::unordered_map<u16, u16> uniqueEnemyIdToStatCount = { static std::unordered_map<u16, u16> uniqueEnemyIdToStatCount = {
{ ACTOR_EN_ANUBICE, COUNT_ENEMIES_DEFEATED_ANUBIS }, { ACTOR_EN_ANUBICE, COUNT_ENEMIES_DEFEATED_ANUBIS },
{ ACTOR_EN_AM, COUNT_ENEMIES_DEFEATED_ARMOS }, { ACTOR_EN_AM, COUNT_ENEMIES_DEFEATED_ARMOS },
@ -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

@ -69,7 +69,7 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
return; return;
} }
Color_RGBA8 textboxColor = { 0, 0, 0, 80}; Color_RGBA8 textboxColor = { 0, 0, 0, 80 };
Color_RGBA8 textColor = { 255, 255, 255, 255 }; Color_RGBA8 textColor = { 255, 255, 255, 255 };
if (CVarGetInteger(CVAR_COSMETIC("HUD.NameTagActorBackground.Changed"), 0)) { if (CVarGetInteger(CVAR_COSMETIC("HUD.NameTagActorBackground.Changed"), 0)) {
@ -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 HORIZONTAL_SPACE(uint8_t x) {
return "\x7F\x02"s + char(x);
}
std::string GO_TO(uint16_t x) {
return "\x7F\x03"s + char(x >> 8) + char(x & 0x00FF);
}
std::string INSTANT_TEXT_ON() { return "\x7F\x04"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) {
return "\x7F\x08"s + char(x);
}
std::string CLOSE_AFTER(uint8_t x) {
return "\x7F\x0A"s + char(x);
}
std::string PLAYER_NAME() { return "\x7F\x0B"s; }
std::string PLAY_OCARINA() { return "\x7F\x0C"s; }
std::string ITEM_OBTAINED(uint8_t x) {
return "\x7F\x0F"s + char(x);
}
std::string SET_SPEED(uint8_t x) {
return "\x7F\x10"s + char(x);
}
std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"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; }
} }
std::string WAIT_FOR_INPUT() {
return "\x7F\x01"s;
}
std::string HORIZONTAL_SPACE(uint8_t x) {
return "\x7F\x02"s + char(x);
}
std::string GO_TO(uint16_t x) {
return "\x7F\x03"s + char(x >> 8) + char(x & 0x00FF);
}
std::string INSTANT_TEXT_ON() {
return "\x7F\x04"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) {
return "\x7F\x08"s + char(x);
}
std::string CLOSE_AFTER(uint8_t x) {
return "\x7F\x0A"s + char(x);
}
std::string PLAYER_NAME() {
return "\x7F\x0B"s;
}
std::string PLAY_OCARINA() {
return "\x7F\x0C"s;
}
std::string ITEM_OBTAINED(uint8_t x) {
return "\x7F\x0F"s + char(x);
}
std::string SET_SPEED(uint8_t x) {
return "\x7F\x10"s + char(x);
}
std::string SKULLTULAS_DESTROYED() {
return "\x7F\x15"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

File diff suppressed because it is too large Load diff

View file

@ -2422,4 +2422,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

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

View file

@ -13,16 +13,11 @@
#include "../hint.h" #include "../hint.h"
#include "../static_data.h" #include "../static_data.h"
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 _dungeonLimit) {
uint8_t _fixed,
uint8_t _copies,
std::function<bool(RandomizerCheck)> _filter,
uint8_t _dungeonLimit){
name = _name; name = _name;
type = _type; type = _type;
weight = _weight; weight = _weight;
@ -30,10 +25,12 @@ HintDistributionSetting::HintDistributionSetting(std::string _name,
copies = _copies; copies = _copies;
filter = _filter; filter = _filter;
dungeonLimit = _dungeonLimit; dungeonLimit = _dungeonLimit;
} }
HintText::HintText(CustomMessage clearText_, std::vector<CustomMessage> ambiguousText_, std::vector<CustomMessage> obscureText_) HintText::HintText(CustomMessage clearText_, std::vector<CustomMessage> ambiguousText_,
: clearText(std::move(clearText_)), ambiguousText(std::move(ambiguousText_)), obscureText(std::move(obscureText_)){} std::vector<CustomMessage> obscureText_)
: clearText(std::move(clearText_)), ambiguousText(std::move(ambiguousText_)), obscureText(std::move(obscureText_)) {
}
const CustomMessage& HintText::GetClear() const { const CustomMessage& HintText::GetClear() const {
return clearText; return clearText;
@ -44,7 +41,7 @@ const CustomMessage& HintText::GetObscure() const {
} }
const CustomMessage& HintText::GetObscure(uint8_t selection) const { const CustomMessage& HintText::GetObscure(uint8_t selection) const {
if (obscureText.size() > selection){ if (obscureText.size() > selection) {
return obscureText[selection]; return obscureText[selection];
} else if (obscureText.size() > 0) { } else if (obscureText.size() > 0) {
return obscureText[0]; return obscureText[0];
@ -57,7 +54,7 @@ const CustomMessage& HintText::GetAmbiguous() const {
} }
const CustomMessage& HintText::GetAmbiguous(uint8_t selection) const { const CustomMessage& HintText::GetAmbiguous(uint8_t selection) const {
if (ambiguousText.size() > selection){ if (ambiguousText.size() > selection) {
return ambiguousText[selection]; return ambiguousText[selection];
} else if (ambiguousText.size() > 0) { } else if (ambiguousText.size() > 0) {
return ambiguousText[0]; return ambiguousText[0];
@ -65,11 +62,11 @@ const CustomMessage& HintText::GetAmbiguous(uint8_t selection) const {
return clearText; return clearText;
} }
uint8_t HintText::GetAmbiguousSize() const{ uint8_t HintText::GetAmbiguousSize() const {
return ambiguousText.size(); return ambiguousText.size();
} }
uint8_t HintText::GetObscureSize() const{ uint8_t HintText::GetObscureSize() const {
return obscureText.size(); return obscureText.size();
} }
@ -96,65 +93,64 @@ 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
// Will be replaced with a better system once more customisable hint pools are added // Will be replaced with a better system once more customisable hint pools are added
uint32_t range = RHT_JUNK71 - RHT_JUNK01; uint32_t range = RHT_JUNK71 - RHT_JUNK01;
return (RandomizerHintTextKey)(Random(0, range) + RHT_JUNK01); return (RandomizerHintTextKey)(Random(0, range) + RHT_JUNK01);
} }
RandomizerHintTextKey GetRandomGanonJoke(){ RandomizerHintTextKey GetRandomGanonJoke() {
uint32_t range = RHT_GANON_JOKE11 - RHT_GANON_JOKE01; uint32_t range = RHT_GANON_JOKE11 - RHT_GANON_JOKE01;
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();
} }
bool FilterFoolishLocations(RandomizerCheck loc){ bool FilterFoolishLocations(RandomizerCheck loc) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return ctx->GetItemLocation(loc)->IsFoolishCandidate(); return ctx->GetItemLocation(loc)->IsFoolishCandidate();
} }
bool FilterSongLocations(RandomizerCheck loc){ bool FilterSongLocations(RandomizerCheck loc) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return Rando::StaticData::GetLocation(loc)->GetRCType() == RCTYPE_SONG_LOCATION; return Rando::StaticData::GetLocation(loc)->GetRCType() == RCTYPE_SONG_LOCATION;
} }
bool FilterOverworldLocations(RandomizerCheck loc){ bool FilterOverworldLocations(RandomizerCheck loc) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return Rando::StaticData::GetLocation(loc)->IsOverworld(); return Rando::StaticData::GetLocation(loc)->IsOverworld();
} }
bool FilterDungeonLocations(RandomizerCheck loc){ bool FilterDungeonLocations(RandomizerCheck loc) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return Rando::StaticData::GetLocation(loc)->IsDungeon(); return Rando::StaticData::GetLocation(loc)->IsDungeon();
} }
bool FilterGoodItems(RandomizerCheck loc){ bool FilterGoodItems(RandomizerCheck loc) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
return ctx->GetItemLocation(loc)->GetPlacedItem().IsMajorItem(); return ctx->GetItemLocation(loc)->GetPlacedItem().IsMajorItem();
} }
bool NoFilter(RandomizerCheck loc){ bool NoFilter(RandomizerCheck loc) {
return true; return true;
} }
@ -225,15 +221,16 @@ 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)) {
stones = std::max<uint8_t>({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).Get() }); stones = std::max<uint8_t>({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).Get() });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 6 )}); stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 6) });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 6 )}); stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 6) });
} }
return stones; return stones;
} }
@ -245,15 +242,17 @@ 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) &&
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 3 )}); 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) });
} }
return medallions; return medallions;
} }
@ -271,45 +270,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;
}), }),
@ -322,30 +331,31 @@ static std::vector<RandomizerCheck> GetEmptyGossipStones() {
static std::vector<RandomizerCheck> GetAccessibleGossipStones(const RandomizerCheck hintedLocation = RC_GANON) { static std::vector<RandomizerCheck> GetAccessibleGossipStones(const RandomizerCheck hintedLocation = RC_GANON) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
//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 gossip stone locations. // reachability search for gossip stone locations.
RandomizerGet originalItem = ctx->GetItemLocation(hintedLocation)->GetPlacedRandomizerGet(); RandomizerGet originalItem = ctx->GetItemLocation(hintedLocation)->GetPlacedRandomizerGet();
ctx->GetItemLocation(hintedLocation)->SetPlacedItem(RG_NONE); ctx->GetItemLocation(hintedLocation)->SetPlacedItem(RG_NONE);
ctx->GetLogic()->Reset(); ctx->GetLogic()->Reset();
auto accessibleGossipStones = ReachabilitySearch(Rando::StaticData::GetGossipStoneLocations()); auto accessibleGossipStones = ReachabilitySearch(Rando::StaticData::GetGossipStoneLocations());
//Give the item back to the location // Give the item back to the location
ctx->GetItemLocation(hintedLocation)->SetPlacedItem(originalItem); ctx->GetItemLocation(hintedLocation)->SetPlacedItem(originalItem);
return accessibleGossipStones; return accessibleGossipStones;
} }
bool IsReachableWithout(std::vector<RandomizerCheck> locsToCheck, RandomizerCheck excludedCheck, bool resetAfter = true){ bool IsReachableWithout(std::vector<RandomizerCheck> locsToCheck, RandomizerCheck excludedCheck,
//temporarily remove the hinted location's item, and then perform a bool resetAfter = true) {
//reachability search for this check RANDOTODO convert excludedCheck to an ItemLocation // temporarily remove the hinted location's item, and then perform a
// reachability search for this check RANDOTODO convert excludedCheck to an ItemLocation
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
RandomizerGet originalItem = ctx->GetItemLocation(excludedCheck)->GetPlacedRandomizerGet(); RandomizerGet originalItem = ctx->GetItemLocation(excludedCheck)->GetPlacedRandomizerGet();
ctx->GetItemLocation(excludedCheck)->SetPlacedItem(RG_NONE); ctx->GetItemLocation(excludedCheck)->SetPlacedItem(RG_NONE);
ctx->GetLogic()->Reset(); ctx->GetLogic()->Reset();
const auto rechableWithout = ReachabilitySearch(locsToCheck); const auto rechableWithout = ReachabilitySearch(locsToCheck);
ctx->GetItemLocation(excludedCheck)->SetPlacedItem(originalItem); ctx->GetItemLocation(excludedCheck)->SetPlacedItem(originalItem);
if (resetAfter){ if (resetAfter) {
//if resetAfter is on, reset logic we are done // if resetAfter is on, reset logic we are done
ctx->GetLogic()->Reset(); ctx->GetLogic()->Reset();
} }
if (rechableWithout.empty()) { if (rechableWithout.empty()) {
@ -354,43 +364,41 @@ bool IsReachableWithout(std::vector<RandomizerCheck> locsToCheck, RandomizerChec
return true; return true;
} }
static void SetAllInAreaAsHintAccesible(RandomizerArea area, std::vector<RandomizerCheck> locations){ static void SetAllInAreaAsHintAccesible(RandomizerArea area, std::vector<RandomizerCheck> locations) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
std::vector<RandomizerCheck> locsInArea = FilterFromPool(locations, [area, ctx](const RandomizerCheck loc){ std::vector<RandomizerCheck> locsInArea = FilterFromPool(locations, [area, ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetAreas().contains(area); return ctx->GetItemLocation(loc)->GetAreas().contains(area);
}); });
for(RandomizerCheck loc: locsInArea){ for (RandomizerCheck loc : locsInArea) {
ctx->GetItemLocation(loc)->SetHintAccesible(); ctx->GetItemLocation(loc)->SetHintAccesible();
} }
} }
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 = {},
const std::vector<TrialKey> trials = {}, const std::vector<TrialKey> trials = {},
RandomizerCheck firstStone = RC_UNKNOWN_CHECK){ RandomizerCheck firstStone = RC_UNKNOWN_CHECK) {
if (firstStone != RC_UNKNOWN_CHECK && copies > 0){ if (firstStone != RC_UNKNOWN_CHECK && copies > 0) {
AddGossipStoneHint(firstStone, hintType, distributionName, hintKeys, locations, areas, trials); AddGossipStoneHint(firstStone, hintType, distributionName, hintKeys, locations, areas, trials);
copies -= 1; copies -= 1;
} }
for(int c=0; c<copies; c++){ for (int c = 0; c < copies; c++) {
//get a random gossip stone // get a random gossip stone
auto gossipStones = GetEmptyGossipStones(); auto gossipStones = GetEmptyGossipStones();
if (gossipStones.empty()) { if (gossipStones.empty()) {
SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n"); SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n");
@ -401,10 +409,10 @@ static void AddGossipStoneHintCopies(uint8_t copies,
} }
} }
static bool CreateHint(RandomizerCheck location, uint8_t copies, HintType type, std::string distribution){ static bool CreateHint(RandomizerCheck location, uint8_t copies, HintType type, std::string distribution) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
//get a gossip stone accessible without the hinted item // get a gossip stone accessible without the hinted item
std::vector<RandomizerCheck> gossipStoneLocations = GetAccessibleGossipStones(location); std::vector<RandomizerCheck> gossipStoneLocations = GetAccessibleGossipStones(location);
if (gossipStoneLocations.empty()) { if (gossipStoneLocations.empty()) {
SPDLOG_DEBUG("\tNO IN LOGIC GOSSIP STONE\n\n"); SPDLOG_DEBUG("\tNO IN LOGIC GOSSIP STONE\n\n");
@ -413,24 +421,21 @@ static bool CreateHint(RandomizerCheck location, uint8_t copies, HintType type,
RandomizerCheck gossipStone = RandomElement(gossipStoneLocations); RandomizerCheck gossipStone = RandomElement(gossipStoneLocations);
RandomizerArea area = ctx->GetItemLocation(location)->GetRandomArea(); RandomizerArea area = ctx->GetItemLocation(location)->GetRandomArea();
//Set that hints are accesible // Set that hints are accesible
ctx->GetItemLocation(location)->SetHintAccesible(); ctx->GetItemLocation(location)->SetHintAccesible();
if (type == HINT_TYPE_FOOLISH){ if (type == HINT_TYPE_FOOLISH) {
SetAllInAreaAsHintAccesible(area, ctx->allLocations); SetAllInAreaAsHintAccesible(area, ctx->allLocations);
} }
AddGossipStoneHintCopies(copies, type, distribution, {}, {location}, {area}, {}, gossipStone); AddGossipStoneHintCopies(copies, type, distribution, {}, { location }, { area }, {}, gossipStone);
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
if (GetEmptyGossipStones().size() < copies) { if (GetEmptyGossipStones().size() < copies) {
SPDLOG_DEBUG("\tNOT ENOUGH GOSSIP STONES TO PLACE HINTS\n\n"); SPDLOG_DEBUG("\tNOT ENOUGH GOSSIP STONES TO PLACE HINTS\n\n");
return RC_UNKNOWN_CHECK; return RC_UNKNOWN_CHECK;
@ -438,12 +443,13 @@ static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHi
RandomizerCheck hintedLocation; RandomizerCheck hintedLocation;
bool placed = false; bool placed = false;
while (!placed){ while (!placed) {
if (possibleHintLocations.empty()) { if (possibleHintLocations.empty()) {
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());
@ -459,37 +465,38 @@ static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHi
} }
static std::vector<RandomizerCheck> FilterHintability(std::vector<RandomizerCheck>& locations, static std::vector<RandomizerCheck> FilterHintability(std::vector<RandomizerCheck>& locations,
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);
}); });
} }
static void CreateJunkHints(uint8_t numHints) { static void CreateJunkHints(uint8_t numHints) {
for(uint8_t c = 0; c < numHints; c++){ for (uint8_t c = 0; c < numHints; c++) {
//duplicate junk hints are possible for now // duplicate junk hints are possible for now
AddGossipStoneHintCopies(1, HINT_TYPE_HINT_KEY, "Junk", {GetRandomJunkHint()}); AddGossipStoneHintCopies(1, HINT_TYPE_HINT_KEY, "Junk", { GetRandomJunkHint() });
} }
} }
static void CreateTrialHints(uint8_t copies) { static void CreateTrialHints(uint8_t copies) {
if (copies > 0) { if (copies > 0) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_TRIAL_COUNT).Is(6)) {//six trials if (ctx->GetOption(RSK_TRIAL_COUNT).Is(6)) { // six trials
AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", {RHT_SIX_TRIALS}); AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", { RHT_SIX_TRIALS });
} 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 =
if (ctx->GetOption(RSK_TRIAL_COUNT).Get() >= 4) {//4 or 5 required trials, get skipped trials ctx->GetTrials()->GetTrialList(); // there's probably a way to remove this assignment
trials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsSkipped();}); if (ctx->GetOption(RSK_TRIAL_COUNT).Get() >= 4) { // 4 or 5 required trials, get skipped trials
} else {//1 to 3 trials, get requried trials trials = FilterFromPool(trials, [](TrialInfo* trial) { return trial->IsSkipped(); });
auto requiredTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsRequired();}); } else { // 1 to 3 trials, get requried trials
auto requiredTrials = FilterFromPool(trials, [](TrialInfo* trial) { return trial->IsRequired(); });
} }
for (auto& trial : trials) {//create a hint for each hinted trial for (auto& trial : trials) { // create a hint for each hinted trial
AddGossipStoneHintCopies(copies, HINT_TYPE_TRIAL, "Trial", {}, {}, {}, {trial->GetTrialKey()}); AddGossipStoneHintCopies(copies, HINT_TYPE_TRIAL, "Trial", {}, {}, {}, { trial->GetTrialKey() });
} }
} }
} }
@ -497,29 +504,35 @@ static void CreateTrialHints(uint8_t copies) {
void CreateWarpSongTexts() { void CreateWarpSongTexts() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_WARP_SONG_HINTS)){ if (ctx->GetOption(RSK_WARP_SONG_HINTS)) {
auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false); auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false);
for (auto entrance : warpSongEntrances) { for (auto entrance : warpSongEntrances) {
//RANDOTODO make random // RANDOTODO make random
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;
@ -528,75 +541,92 @@ void CreateWarpSongTexts() {
} }
} }
int32_t getRandomWeight(int32_t totalWeight){ int32_t getRandomWeight(int32_t totalWeight) {
if (totalWeight <= 1){ if (totalWeight <= 1) {
return 1; return 1;
} }
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,
int32_t totalWeight = junkWieght; //Start with our Junk Weight, the natural chance of a junk hint 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
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
if (addFixed){ totalWeight += distTable[c].weight; // Note that PlaceHints will set weights of distributions to zero if it
// can't place anything from them
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.
//and that all weights have been 0'd out for another reason, and skips to placing all junk hints while (stoneCount > 0 &&
for (size_t distribution = 0; distribution < distTable.size(); distribution++){ totalWeight >
currentWeight -= distTable[distribution].weight; //go over each distribution, subtracting the weight each time. Once we reach zero or less, 0) { // Loop until we run out of stones or have no TotalWeight. 0 totalWeight means junkWeight is 0
if (currentWeight <= 0){ //tell the system to make 1 of that hint, unless not enough stones remain // and that all weights have been 0'd out for another reason, and skips to placing all junk hints
if (stoneCount >= distTable[distribution].copies && distTable[distribution].copies > 0){ for (size_t distribution = 0; distribution < distTable.size(); distribution++) {
selected[distribution] += 1; //if we have enough stones, and copies are not zero, assign 1 to this hint type, remove the stones, and break 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 (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
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 >
selected[selected.size()-1] += 1; 0) { // zero TotalWeight breaks the while loop and hits the fallback, so skipping this is fine in that case
selected[selected.size() - 1] += 1;
stoneCount -= 1; stoneCount -= 1;
} }
currentWeight = getRandomWeight(totalWeight); currentWeight = getRandomWeight(totalWeight);
} }
//if stones are left, assign junk to every remaining stone as a fallback. // if stones are left, assign junk to every remaining stone as a fallback.
if (stoneCount > 0){ if (stoneCount > 0) {
selected[selected.size()-1] += stoneCount; selected[selected.size() - 1] += stoneCount;
} }
} }
uint8_t PlaceHints(std::vector<uint8_t>& selectedHints, std::vector<HintDistributionSetting>& distTable){ uint8_t PlaceHints(std::vector<uint8_t>& selectedHints, std::vector<HintDistributionSetting>& distTable) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
uint8_t curSlot = 0; uint8_t curSlot = 0;
for (HintDistributionSetting distribution : distTable){ for (HintDistributionSetting distribution : distTable) {
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
distTable[curSlot].copies = 0;//and prevent future distribution from choosing this slot // of this seed generation
distTable[curSlot].copies = 0; // and prevent future distribution from choosing this slot
distTable[curSlot].weight = 0; distTable[curSlot].weight = 0;
return hintsToRemove; return hintsToRemove;
} }
if(Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()){ if (Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()) {
distribution.dungeonLimit -= 1; distribution.dungeonLimit -= 1;
if (distribution.dungeonLimit == 0){ if (distribution.dungeonLimit == 0) {
FilterFromPool(hintTypePool, FilterOverworldLocations); FilterFromPool(hintTypePool, FilterOverworldLocations);
} }
} }
@ -615,23 +645,22 @@ void CreateStoneHints() {
std::vector<HintDistributionSetting> distTable = hintSetting.distTable; std::vector<HintDistributionSetting> distTable = hintSetting.distTable;
// Apply impa's song exclusions when zelda is skipped // Apply impa's song exclusions when zelda is skipped
if(ctx->GetOption(RSK_SKIP_CHILD_ZELDA)){ if (ctx->GetOption(RSK_SKIP_CHILD_ZELDA)) {
ctx->GetItemLocation(RC_SONG_FROM_IMPA)->SetHintAccesible(); ctx->GetItemLocation(RC_SONG_FROM_IMPA)->SetHintAccesible();
} }
// Add 'always' location hints // Add 'always' location hints
std::vector<RandomizerCheck> alwaysHintLocations = {}; std::vector<RandomizerCheck> alwaysHintLocations = {};
if (hintSetting.alwaysCopies > 0) { if (hintSetting.alwaysCopies > 0) {
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)){ if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)) {
// 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)));
}); });
if (gregLocations.size() > 0){ if (gregLocations.size() > 0) {
alwaysHintLocations.push_back(gregLocations[0]); alwaysHintLocations.push_back(gregLocations[0]);
} }
} }
@ -648,42 +677,46 @@ void CreateStoneHints() {
} }
} }
//Add 'trial' location hints // Add 'trial' location hints
if (ctx->GetOption(RSK_GANONS_TRIALS).IsNot(RO_GANONS_TRIALS_SKIP)) { if (ctx->GetOption(RSK_GANONS_TRIALS).IsNot(RO_GANONS_TRIALS_SKIP)) {
CreateTrialHints(hintSetting.trialCopies); CreateTrialHints(hintSetting.trialCopies);
} }
size_t totalStones = GetEmptyGossipStones().size(); size_t totalStones = GetEmptyGossipStones().size();
std::vector<uint8_t> selectedHints = {}; std::vector<uint8_t> selectedHints = {};
for (size_t c=0; c < distTable.size(); c++){ for (size_t c = 0; c < distTable.size(); c++) {
selectedHints.push_back(0); selectedHints.push_back(0);
} }
selectedHints.push_back(0); selectedHints.push_back(0);
DistributeHints(selectedHints, totalStones, distTable, hintSetting.junkWeight); DistributeHints(selectedHints, totalStones, distTable, hintSetting.junkWeight);
while(totalStones != 0){ while (totalStones != 0) {
totalStones = PlaceHints(selectedHints, distTable); totalStones = PlaceHints(selectedHints, distTable);
if (totalStones != 0){ if (totalStones != 0) {
DistributeHints(selectedHints, totalStones, distTable, hintSetting.junkWeight, false); DistributeHints(selectedHints, totalStones, distTable, hintSetting.junkWeight, false);
} }
} }
//Getting gossip stone locations temporarily sets one location to not be reachable. // Getting gossip stone locations temporarily sets one location to not be reachable.
//Call the function one last time to get rid of false positives on locations not // Call the function one last time to get rid of false positives on locations not
//being reachable. // being reachable.
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) {
if (found.size() > 0){ return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == items[c];
});
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 {
@ -695,16 +728,18 @@ std::vector<RandomizerCheck> FindItemsAndMarkHinted(std::vector<RandomizerGet> i
void CreateChildAltarHint() { void CreateChildAltarHint() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled() && ctx->GetOption(RSK_TOT_ALTAR_HINT)){ if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled() && 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) ||
stoneLocs = FindItemsAndMarkHinted({RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE}, {}); ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) {
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) {
if (loc != RC_UNKNOWN_CHECK) { if (loc != RC_UNKNOWN_CHECK) {
stoneAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); stoneAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea());
} }
@ -715,20 +750,23 @@ void CreateChildAltarHint() {
void CreateAdultAltarHint() { void CreateAdultAltarHint() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
if (!ctx->GetHint(RH_ALTAR_ADULT)->IsEnabled()){ if (!ctx->GetHint(RH_ALTAR_ADULT)->IsEnabled()) {
std::vector<RandomizerCheck> medallionLocs = {}; std::vector<RandomizerCheck> medallionLocs = {};
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,
{RC_ALTAR_HINT_ADULT}); RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION },
{ RC_ALTAR_HINT_ADULT });
} }
} }
std::vector<RandomizerArea> medallionAreas = {}; std::vector<RandomizerArea> medallionAreas = {};
for (auto loc : medallionLocs){ for (auto loc : medallionLocs) {
if (loc != RC_UNKNOWN_CHECK) { if (loc != RC_UNKNOWN_CHECK) {
medallionAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); medallionAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea());
} }
@ -737,82 +775,89 @@ void CreateAdultAltarHint() {
} }
} }
void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){ void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
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) {
locations = FindItemsAndMarkHinted(staticData.targetItems, staticData.hintChecks); locations = FindItemsAndMarkHinted(staticData.targetItems, staticData.hintChecks);
} else { } else {
for(auto check: staticData.targetChecks){ for (auto check : staticData.targetChecks) {
locations.push_back(check); locations.push_back(check);
} }
} }
std::vector<RandomizerArea> areas = {}; std::vector<RandomizerArea> areas = {};
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);
areas.push_back(RA_NONE); areas.push_back(RA_NONE);
} else { } else {
areas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); areas.push_back(ctx->GetItemLocation(loc)->GetRandomArea());
} }
} }
//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,
//RANDOTODO choose area in case there are multiple bool yourPocket = false) {
// 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);
std::vector<RandomizerArea> areas = {}; std::vector<RandomizerArea> areas = {};
for (auto loc : locations){ for (auto loc : locations) {
areas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); areas.push_back(ctx->GetItemLocation(loc)->GetRandomArea());
} }
ctx->AddHint(hintKey, Hint(hintKey, HINT_TYPE_AREA, hintTextKeys, locations, areas, {}, yourPocket)); ctx->AddHint(hintKey, Hint(hintKey, HINT_TYPE_AREA, hintTextKeys, locations, areas, {}, yourPocket));
} }
void CreateGanondorfJoke(){ void CreateGanondorfJoke() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
if (!ctx->GetHint(RH_GANONDORF_JOKE)->IsEnabled()){ if (!ctx->GetHint(RH_GANONDORF_JOKE)->IsEnabled()) {
ctx->AddHint(RH_GANONDORF_JOKE, Hint(RH_GANONDORF_JOKE, HINT_TYPE_HINT_KEY, {GetRandomGanonJoke()})); ctx->AddHint(RH_GANONDORF_JOKE, Hint(RH_GANONDORF_JOKE, HINT_TYPE_HINT_KEY, { GetRandomGanonJoke() }));
} }
} }
void CreateGanondorfHint(){ 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(
{RG_LIGHT_ARROWS, RG_MASTER_SWORD}, {RC_GANONDORF_HINT}, true); 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);
} 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);
} }
} }
} }
void CreateStaticHints(){ void CreateStaticHints() {
CreateChildAltarHint(); CreateChildAltarHint();
CreateAdultAltarHint(); CreateAdultAltarHint();
CreateGanondorfJoke(); CreateGanondorfJoke();
CreateGanondorfHint(); CreateGanondorfHint();
for (auto[hint, staticData] : StaticData::staticHintInfoMap){ for (auto [hint, staticData] : StaticData::staticHintInfoMap) {
CreateStaticHintFromData(hint, staticData); CreateStaticHintFromData(hint, staticData);
} }
} }
void CreateAllHints(){ void CreateAllHints() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
CreateStaticHints(); CreateStaticHints();

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,
@ -59,45 +39,45 @@ const std::array<RandomizerGet, 59> alwaysItems = {
RG_FARORES_WIND, RG_FARORES_WIND,
RG_NAYRUS_LOVE, RG_NAYRUS_LOVE,
RG_GREG_RUPEE, RG_GREG_RUPEE,
RG_PROGRESSIVE_HOOKSHOT, //2 progressive hookshots RG_PROGRESSIVE_HOOKSHOT, // 2 progressive hookshots
RG_PROGRESSIVE_HOOKSHOT, RG_PROGRESSIVE_HOOKSHOT,
RG_DEKU_SHIELD, RG_DEKU_SHIELD,
RG_HYLIAN_SHIELD, RG_HYLIAN_SHIELD,
RG_PROGRESSIVE_STRENGTH, //3 progressive strength upgrades RG_PROGRESSIVE_STRENGTH, // 3 progressive strength upgrades
RG_PROGRESSIVE_STRENGTH, RG_PROGRESSIVE_STRENGTH,
RG_PROGRESSIVE_STRENGTH, RG_PROGRESSIVE_STRENGTH,
RG_PROGRESSIVE_SCALE, //2 progressive scales RG_PROGRESSIVE_SCALE, // 2 progressive scales
RG_PROGRESSIVE_SCALE, RG_PROGRESSIVE_SCALE,
RG_PROGRESSIVE_BOW, //3 progressive Bows RG_PROGRESSIVE_BOW, // 3 progressive Bows
RG_PROGRESSIVE_BOW, RG_PROGRESSIVE_BOW,
RG_PROGRESSIVE_BOW, RG_PROGRESSIVE_BOW,
RG_PROGRESSIVE_SLINGSHOT, //3 progressive bullet bags RG_PROGRESSIVE_SLINGSHOT, // 3 progressive bullet bags
RG_PROGRESSIVE_SLINGSHOT, RG_PROGRESSIVE_SLINGSHOT,
RG_PROGRESSIVE_SLINGSHOT, RG_PROGRESSIVE_SLINGSHOT,
RG_PROGRESSIVE_BOMB_BAG, //3 progressive bomb bags RG_PROGRESSIVE_BOMB_BAG, // 3 progressive bomb bags
RG_PROGRESSIVE_BOMB_BAG, RG_PROGRESSIVE_BOMB_BAG,
RG_PROGRESSIVE_BOMB_BAG, RG_PROGRESSIVE_BOMB_BAG,
RG_PROGRESSIVE_WALLET, //2 progressive wallets RG_PROGRESSIVE_WALLET, // 2 progressive wallets
RG_PROGRESSIVE_WALLET, RG_PROGRESSIVE_WALLET,
RG_PROGRESSIVE_MAGIC_METER, //2 progressive magic meters RG_PROGRESSIVE_MAGIC_METER, // 2 progressive magic meters
RG_PROGRESSIVE_MAGIC_METER, RG_PROGRESSIVE_MAGIC_METER,
RG_DOUBLE_DEFENSE, RG_DOUBLE_DEFENSE,
RG_PROGRESSIVE_STICK_UPGRADE, //2 stick upgrades RG_PROGRESSIVE_STICK_UPGRADE, // 2 stick upgrades
RG_PROGRESSIVE_STICK_UPGRADE, RG_PROGRESSIVE_STICK_UPGRADE,
RG_PROGRESSIVE_NUT_UPGRADE, //2 nut upgrades RG_PROGRESSIVE_NUT_UPGRADE, // 2 nut upgrades
RG_PROGRESSIVE_NUT_UPGRADE, RG_PROGRESSIVE_NUT_UPGRADE,
RG_RECOVERY_HEART, //6 recovery hearts RG_RECOVERY_HEART, // 6 recovery hearts
RG_RECOVERY_HEART, RG_RECOVERY_HEART,
RG_RECOVERY_HEART, RG_RECOVERY_HEART,
RG_RECOVERY_HEART, RG_RECOVERY_HEART,
RG_RECOVERY_HEART, RG_RECOVERY_HEART,
RG_RECOVERY_HEART, RG_RECOVERY_HEART,
RG_BOMBS_5, //2 RG_BOMBS_5, // 2
RG_BOMBS_5, RG_BOMBS_5,
RG_BOMBS_10, RG_BOMBS_10,
RG_BOMBS_20, RG_BOMBS_20,
RG_ARROWS_5, RG_ARROWS_5,
RG_ARROWS_10, //5 RG_ARROWS_10, // 5
RG_ARROWS_10, RG_ARROWS_10,
RG_ARROWS_10, RG_ARROWS_10,
RG_TREASURE_GAME_HEART, RG_TREASURE_GAME_HEART,
@ -128,7 +108,7 @@ const std::array<RandomizerGet, 44> easyItems = {
RG_PROGRESSIVE_SLINGSHOT, RG_PROGRESSIVE_SLINGSHOT,
RG_PROGRESSIVE_BOMB_BAG, RG_PROGRESSIVE_BOMB_BAG,
RG_DOUBLE_DEFENSE, RG_DOUBLE_DEFENSE,
RG_HEART_CONTAINER, //16 Heart Containers RG_HEART_CONTAINER, // 16 Heart Containers
RG_HEART_CONTAINER, RG_HEART_CONTAINER,
RG_HEART_CONTAINER, RG_HEART_CONTAINER,
RG_HEART_CONTAINER, RG_HEART_CONTAINER,
@ -144,7 +124,7 @@ const std::array<RandomizerGet, 44> easyItems = {
RG_HEART_CONTAINER, RG_HEART_CONTAINER,
RG_HEART_CONTAINER, RG_HEART_CONTAINER,
RG_HEART_CONTAINER, RG_HEART_CONTAINER,
RG_PIECE_OF_HEART, //3 heart pieces RG_PIECE_OF_HEART, // 3 heart pieces
RG_PIECE_OF_HEART, RG_PIECE_OF_HEART,
RG_PIECE_OF_HEART, RG_PIECE_OF_HEART,
}; };
@ -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_TREASURE_GAME_GREEN_RUPEE, RG_TREASURE_GAME_GREEN_RUPEE, RG_TREASURE_GAME_GREEN_RUPEE, RG_ARROWS_10, RG_GREEN_RUPEE, RG_PURPLE_RUPEE,
RG_TREASURE_GAME_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,103 +263,33 @@ 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,
//RG_POCKET_CUCCO, // RG_POCKET_CUCCO,
RG_COJIRO, RG_COJIRO,
RG_ODD_MUSHROOM, RG_ODD_MUSHROOM,
RG_POACHERS_SAW, RG_POACHERS_SAW,
@ -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,12 +318,13 @@ 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);
} }
//Ice Trap is the last item in JunkPoolItems, so subtract 1 to never hit that index // Ice Trap is the last item in JunkPoolItems, so subtract 1 to never hit that index
uint8_t idx = Random(0, JunkPoolItems.size() - 1); uint8_t idx = Random(0, JunkPoolItems.size() - 1);
return JunkPoolItems[idx]; return JunkPoolItems[idx];
} }
@ -447,7 +337,7 @@ static RandomizerGet GetPendingJunkItem() {
return RandomElement(PendingJunkPool, true); return RandomElement(PendingJunkPool, true);
} }
//Replace junk items in the pool with pending junk // Replace junk items in the pool with pending junk
static void ReplaceMaxItem(const RandomizerGet itemToReplace, int max) { static void ReplaceMaxItem(const RandomizerGet itemToReplace, int max) {
int itemCount = 0; int itemCount = 0;
for (size_t i = 0; i < ItemPool.size(); i++) { for (size_t i = 0; i < ItemPool.size(); i++) {
@ -461,7 +351,7 @@ static void ReplaceMaxItem(const RandomizerGet itemToReplace, int max) {
} }
void PlaceJunkInExcludedLocation(const RandomizerCheck il) { void PlaceJunkInExcludedLocation(const RandomizerCheck il) {
//place a non-advancement item in this location // place a non-advancement item in this location
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
for (size_t i = 0; i < ItemPool.size(); i++) { for (size_t i = 0; i < ItemPool.size(); i++) {
if (!Rando::StaticData::RetrieveItem(ItemPool[i]).IsAdvancement()) { if (!Rando::StaticData::RetrieveItem(ItemPool[i]).IsAdvancement()) {
@ -561,16 +451,16 @@ static void SetMinimalItemPool() {
ReplaceMaxItem(RG_PROGRESSIVE_BOMB_BAG, 1); ReplaceMaxItem(RG_PROGRESSIVE_BOMB_BAG, 1);
ReplaceMaxItem(RG_PIECE_OF_HEART, 0); ReplaceMaxItem(RG_PIECE_OF_HEART, 0);
// Need an extra heart container when starting with 1 heart to be able to reach 3 hearts // Need an extra heart container when starting with 1 heart to be able to reach 3 hearts
ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).Get() == 18)? 1 : 0); ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).Get() == 18) ? 1 : 0);
} }
void GenerateItemPool() { void GenerateItemPool() {
//RANDOTODO proper removal of items not in pool or logically relevant instead of dummy checks. // RANDOTODO proper removal of items not in pool or logically relevant instead of dummy checks.
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
ItemPool.clear(); ItemPool.clear();
PendingJunkPool.clear(); PendingJunkPool.clear();
//Initialize ice trap models to always major items // Initialize ice trap models to always major items
ctx->possibleIceTrapModels = { ctx->possibleIceTrapModels = {
RG_MIRROR_SHIELD, RG_MIRROR_SHIELD,
RG_BOOMERANG, RG_BOOMERANG,
@ -596,9 +486,9 @@ void GenerateItemPool() {
RG_PROGRESSIVE_SCALE, RG_PROGRESSIVE_SCALE,
RG_PROGRESSIVE_MAGIC_METER, RG_PROGRESSIVE_MAGIC_METER,
}; };
//Check song shuffle and dungeon reward shuffle just for ice traps // Check song shuffle and dungeon reward shuffle just for ice traps
if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE)) { if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE)) {
//Push item ids for songs // Push item ids for songs
ctx->possibleIceTrapModels.push_back(RG_ZELDAS_LULLABY); ctx->possibleIceTrapModels.push_back(RG_ZELDAS_LULLABY);
ctx->possibleIceTrapModels.push_back(RG_EPONAS_SONG); ctx->possibleIceTrapModels.push_back(RG_EPONAS_SONG);
ctx->possibleIceTrapModels.push_back(RG_SARIAS_SONG); ctx->possibleIceTrapModels.push_back(RG_SARIAS_SONG);
@ -613,7 +503,7 @@ void GenerateItemPool() {
ctx->possibleIceTrapModels.push_back(RG_PRELUDE_OF_LIGHT); ctx->possibleIceTrapModels.push_back(RG_PRELUDE_OF_LIGHT);
} }
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_ANYWHERE)) { if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_ANYWHERE)) {
//Push item ids for dungeon rewards // Push item ids for dungeon rewards
ctx->possibleIceTrapModels.push_back(RG_KOKIRI_EMERALD); ctx->possibleIceTrapModels.push_back(RG_KOKIRI_EMERALD);
ctx->possibleIceTrapModels.push_back(RG_GORON_RUBY); ctx->possibleIceTrapModels.push_back(RG_GORON_RUBY);
ctx->possibleIceTrapModels.push_back(RG_ZORA_SAPPHIRE); ctx->possibleIceTrapModels.push_back(RG_ZORA_SAPPHIRE);
@ -634,7 +524,7 @@ void GenerateItemPool() {
ctx->PlaceItemInLocation(RC_GANON, RG_TRIFORCE); // Win condition ctx->PlaceItemInLocation(RC_GANON, RG_TRIFORCE); // Win condition
} }
//Fixed item locations // Fixed item locations
ctx->PlaceItemInLocation(RC_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER); ctx->PlaceItemInLocation(RC_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER);
if (ctx->GetOption(RSK_SHUFFLE_KOKIRI_SWORD)) { if (ctx->GetOption(RSK_SHUFFLE_KOKIRI_SWORD)) {
@ -702,7 +592,7 @@ void GenerateItemPool() {
} }
if (ctx->GetOption(RSK_SHUFFLE_BEEHIVES)) { if (ctx->GetOption(RSK_SHUFFLE_BEEHIVES)) {
//32 total beehive locations // 32 total beehive locations
AddItemToPool(PendingJunkPool, RG_RED_RUPEE, 23); AddItemToPool(PendingJunkPool, RG_RED_RUPEE, 23);
AddItemToPool(PendingJunkPool, RG_BLUE_RUPEE, 9); AddItemToPool(PendingJunkPool, RG_BLUE_RUPEE, 9);
} }
@ -785,7 +675,7 @@ void GenerateItemPool() {
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)) {
if (/*!ProgressiveGoronSword TODO: Implement Progressive Goron Sword*/true) { if (/*!ProgressiveGoronSword TODO: Implement Progressive Goron Sword*/ true) {
AddItemToMainPool(RG_GIANTS_KNIFE); AddItemToMainPool(RG_GIANTS_KNIFE);
} }
if (ctx->GetOption(RSK_BOMBCHU_BAG)) { if (ctx->GetOption(RSK_BOMBCHU_BAG)) {
@ -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);
@ -909,7 +800,7 @@ void GenerateItemPool() {
AddItemToMainPool(RG_BOMBCHU_20); AddItemToMainPool(RG_BOMBCHU_20);
} }
//Ice Traps // Ice Traps
AddItemToMainPool(RG_ICE_TRAP); AddItemToMainPool(RG_ICE_TRAP);
if (ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUND)->IsVanilla()) { if (ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUND)->IsVanilla()) {
AddItemToMainPool(RG_ICE_TRAP); AddItemToMainPool(RG_ICE_TRAP);
@ -918,7 +809,7 @@ void GenerateItemPool() {
AddItemToMainPool(RG_ICE_TRAP, 4); AddItemToMainPool(RG_ICE_TRAP, 4);
} }
//Gerudo Fortress // Gerudo Fortress
if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE)) { if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE)) {
ctx->PlaceItemInLocation(RC_GF_NORTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true); ctx->PlaceItemInLocation(RC_GF_NORTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true);
ctx->PlaceItemInLocation(RC_GF_NORTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true); ctx->PlaceItemInLocation(RC_GF_NORTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true);
@ -931,10 +822,10 @@ void GenerateItemPool() {
ctx->PlaceItemInLocation(RC_GF_SOUTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true); ctx->PlaceItemInLocation(RC_GF_SOUTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true);
ctx->PlaceItemInLocation(RC_GF_SOUTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true); ctx->PlaceItemInLocation(RC_GF_SOUTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true);
} else { } else {
//Only add key ring if 4 Fortress keys necessary // Only add key ring if 4 Fortress keys necessary
if (ctx->GetOption(RSK_KEYRINGS_GERUDO_FORTRESS) && ctx->GetOption(RSK_KEYRINGS)) { if (ctx->GetOption(RSK_KEYRINGS_GERUDO_FORTRESS) && ctx->GetOption(RSK_KEYRINGS)) {
AddItemToMainPool(RG_GERUDO_FORTRESS_KEY_RING); AddItemToMainPool(RG_GERUDO_FORTRESS_KEY_RING);
//Add junk to make up for missing keys // Add junk to make up for missing keys
for (uint8_t i = 0; i < 3; i++) { for (uint8_t i = 0; i < 3; i++) {
AddItemToMainPool(GetJunkItem()); AddItemToMainPool(GetJunkItem());
} }
@ -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_GERUDO_FORTRESS_KEY_RING); AddItemToPool(PendingJunkPool, RG_GERUDO_FORTRESS_KEY_RING);
} else { } else {
AddItemToPool(PendingJunkPool, RG_GERUDO_FORTRESS_SMALL_KEY); AddItemToPool(PendingJunkPool, RG_GERUDO_FORTRESS_SMALL_KEY);
@ -963,8 +855,9 @@ 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)) {
@ -974,9 +867,9 @@ void GenerateItemPool() {
ctx->PlaceItemInLocation(RC_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, false, true); ctx->PlaceItemInLocation(RC_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, false, true);
} }
//Keys // Keys
//For key rings, need to add as many junk items as "missing" keys // For key rings, need to add as many junk items as "missing" keys
if (ctx->GetOption(RSK_KEYRINGS).IsNot(RO_KEYRINGS_OFF)) { if (ctx->GetOption(RSK_KEYRINGS).IsNot(RO_KEYRINGS_OFF)) {
uint8_t ringJunkAmt = 0; uint8_t ringJunkAmt = 0;
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
@ -998,8 +891,10 @@ void GenerateItemPool() {
AddItemToPool(PendingJunkPool, RG_FISHING_POLE); AddItemToPool(PendingJunkPool, RG_FISHING_POLE);
} }
//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_BOTTOM_OF_THE_WELL_KEY_RING); AddItemToPool(PendingJunkPool, RG_BOTTOM_OF_THE_WELL_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);
} }
} }
@ -1082,17 +981,13 @@ void GenerateItemPool() {
AddItemToPool(ItemPool, RG_FISHING_HOLE_KEY); AddItemToPool(ItemPool, RG_FISHING_HOLE_KEY);
} }
//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
} }
// Shuffle Fairies // Shuffle Fairies
@ -1114,14 +1009,14 @@ void GenerateItemPool() {
} }
} }
//Scrubsanity // Scrubsanity
if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_ALL)) { if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_ALL)) {
//Deku Tree // Deku Tree
if (ctx->GetDungeon(Rando::DEKU_TREE)->IsMQ()) { if (ctx->GetDungeon(Rando::DEKU_TREE)->IsMQ()) {
AddItemToMainPool(RG_DEKU_SHIELD); AddItemToMainPool(RG_DEKU_SHIELD);
} }
//Dodongos Cavern // Dodongos Cavern
AddItemToMainPool(RG_DEKU_STICK_1); AddItemToMainPool(RG_DEKU_STICK_1);
AddItemToMainPool(RG_DEKU_SHIELD); AddItemToMainPool(RG_DEKU_SHIELD);
if (ctx->GetDungeon(Rando::DODONGOS_CAVERN)->IsMQ()) { if (ctx->GetDungeon(Rando::DODONGOS_CAVERN)->IsMQ()) {
@ -1130,12 +1025,12 @@ void GenerateItemPool() {
AddItemToMainPool(RG_DEKU_NUTS_5); AddItemToMainPool(RG_DEKU_NUTS_5);
} }
//Jabu Jabus Belly // Jabu Jabus Belly
if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsVanilla()) { if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsVanilla()) {
AddItemToMainPool(RG_DEKU_NUTS_5); AddItemToMainPool(RG_DEKU_NUTS_5);
} }
//Ganons Castle // Ganons Castle
AddItemToMainPool(RG_BOMBS_5); AddItemToMainPool(RG_BOMBS_5);
AddItemToMainPool(RG_RECOVERY_HEART); AddItemToMainPool(RG_RECOVERY_HEART);
AddItemToMainPool(RG_BLUE_RUPEE); AddItemToMainPool(RG_BLUE_RUPEE);
@ -1143,10 +1038,10 @@ void GenerateItemPool() {
AddItemToMainPool(RG_DEKU_NUTS_5); AddItemToMainPool(RG_DEKU_NUTS_5);
} }
//Overworld Scrubs // Overworld Scrubs
AddItemsToPool(ItemPool, dekuScrubItems); AddItemsToPool(ItemPool, dekuScrubItems);
//Scrubs which sell seeds or arrows sell it based on age, this randomly assigns them // Scrubs which sell seeds or arrows sell it based on age, this randomly assigns them
for (uint8_t i = 0; i < 7; i++) { for (uint8_t i = 0; i < 7; i++) {
if (Random(0, 3)) { if (Random(0, 3)) {
AddItemToMainPool(RG_ARROWS_30); AddItemToMainPool(RG_ARROWS_30);
@ -1165,7 +1060,7 @@ void GenerateItemPool() {
AddItemsToPool(ItemPool, alwaysItems); AddItemsToPool(ItemPool, alwaysItems);
AddItemsToPool(ItemPool, dungeonRewards); AddItemsToPool(ItemPool, dungeonRewards);
//Dungeon pools // Dungeon pools
if (ctx->GetDungeon(Rando::DEKU_TREE)->IsMQ()) { if (ctx->GetDungeon(Rando::DEKU_TREE)->IsMQ()) {
AddItemsToPool(ItemPool, DT_MQ); AddItemsToPool(ItemPool, DT_MQ);
} else { } else {
@ -1218,12 +1113,12 @@ void GenerateItemPool() {
rutoBottles = 0; rutoBottles = 0;
} }
//Add 4 total bottles // Add 4 total bottles
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) &&
@ -1238,9 +1133,10 @@ 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);
} }
@ -1313,7 +1209,7 @@ void GenerateItemPool() {
ReplaceMaxItem(RG_MASTER_SWORD, 0); ReplaceMaxItem(RG_MASTER_SWORD, 0);
} }
if (/*ProgressiveGoronSword TODO: Implement Setting*/false) { if (/*ProgressiveGoronSword TODO: Implement Setting*/ false) {
ReplaceMaxItem(RG_BIGGORON_SWORD, 0); ReplaceMaxItem(RG_BIGGORON_SWORD, 0);
AddItemToMainPool(RG_PROGRESSIVE_GORONSWORD, 2); AddItemToMainPool(RG_PROGRESSIVE_GORONSWORD, 2);
ctx->possibleIceTrapModels.push_back(RG_PROGRESSIVE_GORONSWORD); ctx->possibleIceTrapModels.push_back(RG_PROGRESSIVE_GORONSWORD);
@ -1321,11 +1217,11 @@ void GenerateItemPool() {
ctx->possibleIceTrapModels.push_back(RG_BIGGORON_SWORD); ctx->possibleIceTrapModels.push_back(RG_BIGGORON_SWORD);
} }
//Replace ice traps with junk from the pending junk pool if necessary // Replace ice traps with junk from the pending junk pool if necessary
if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_OFF)) { if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_OFF)) {
ReplaceMaxItem(RG_ICE_TRAP, 0); ReplaceMaxItem(RG_ICE_TRAP, 0);
} }
//Replace all junk items with ice traps for onslaught mode // Replace all junk items with ice traps for onslaught mode
else if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_ONSLAUGHT)) { else if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_ONSLAUGHT)) {
PendingJunkPool.clear(); PendingJunkPool.clear();
for (uint8_t i = 0; i < JunkPoolItems.size() - 3; i++) { // -3 Omits Huge Rupees and Deku Nuts 10 for (uint8_t i = 0; i < JunkPoolItems.size() - 3; i++) { // -3 Omits Huge Rupees and Deku Nuts 10

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