Merge branch 'develop' into ItemName

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

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

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

4
.gitignore vendored
View file

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

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

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

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

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

View file

@ -4,7 +4,6 @@
ActorDB* ActorDB::Instance;
#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_UNSET(_0)
@ -464,7 +463,8 @@ static constexpr std::pair<u16, const char*> actorDescriptionData[] = {
{ ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" },
{ 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() {
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.
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)) {
db.resize(index + 1);
@ -513,7 +514,8 @@ ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& de
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) {
Entry& entry = AddEntry(init.name, init.desc, nextFreeId);
@ -598,7 +600,8 @@ static ActorDBInit EnPartnerInit = {
"En_Partner",
"Ivan",
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,
sizeof(EnPartner),
(ActorFunc)EnPartner_Init,

View file

@ -65,6 +65,7 @@ public:
static void AddBuiltInCustomActors();
int GetEntryCount();
private:
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);

View file

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

View file

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

View file

@ -30,7 +30,8 @@ void RegisterFreezeTime() {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnGameFrameUpdate>(hookId);
hookId = 0;
if (CVAR_FREEZE_TIME_VALUE) {
hookId = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(OnGameFrameUpdateFreezeTime);
hookId =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(OnGameFrameUpdateFreezeTime);
} else {
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)
void OnGameFrameUpdateInfiniteMoney() {
if (
!GameInteractor::IsSaveLoaded(true) ||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))
) {
if (!GameInteractor::IsSaveLoaded(true) || (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))) {
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_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() {
if (!GameInteractor::IsSaveLoaded(true)) {

View file

@ -36,23 +36,19 @@ static int statusTimer = -1;
static int eventTimer = -1;
const char* altTrapTypeCvars[] = {
CVAR_ENHANCEMENT("ExtraTraps.Ice"),
CVAR_ENHANCEMENT("ExtraTraps.Burn"),
CVAR_ENHANCEMENT("ExtraTraps.Shock"),
CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
CVAR_ENHANCEMENT("ExtraTraps.Speed"),
CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
CVAR_ENHANCEMENT("ExtraTraps.Void"),
CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
CVAR_ENHANCEMENT("ExtraTraps.Kill"),
CVAR_ENHANCEMENT("ExtraTraps.Teleport"),
CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"),
CVAR_ENHANCEMENT("ExtraTraps.Shock"), CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
CVAR_ENHANCEMENT("ExtraTraps.Speed"), 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> enabledAddTraps;
for (int i = 0; i < ADD_TRAP_MAX; i++) {
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
}
enabledAddTraps.push_back(static_cast<AltTrapType>(i));
@ -65,7 +61,8 @@ std::vector<AltTrapType> getEnabledAddTraps () {
};
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);
roll = RandomElement(getEnabledAddTraps());
@ -83,7 +80,8 @@ static void RollRandomTrap(uint32_t seed) {
eventTimer = 3;
break;
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;
statusTimer = 200;
Notification::Emit({ .message = "Speed Decreased!" });
@ -92,7 +90,8 @@ static void RollRandomTrap(uint32_t seed) {
eventTimer = 3;
break;
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;
break;
case ADD_AMMO_TRAP:
@ -133,7 +132,8 @@ static void OnPlayerUpdate() {
AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 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;
case ADD_TELEPORT_TRAP: {
int entrance;
@ -199,5 +199,3 @@ void RegisterExtraTraps() {
}
static RegisterShipInitFunc initFunc(RegisterExtraTraps, { CVAR_EXTRA_TRAPS_NAME });

View file

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

View file

@ -3,10 +3,14 @@
#include "soh/cvar_prefixes.h"
#include "soh/Enhancements/enhancementTypes.h"
#define PRESET_ENTRY_S32(cvar, value) { cvar, PRESET_ENTRY_TYPE_S32, value }
#define PRESET_ENTRY_FLOAT(cvar, 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 }
#define PRESET_ENTRY_S32(cvar, value) \
{ cvar, PRESET_ENTRY_TYPE_S32, value }
#define PRESET_ENTRY_FLOAT(cvar, 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
@ -20,16 +24,14 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterOwl"), 1),
// Skips & Speed-ups
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
// Graphics
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("WidescreenActorCulling"), 1),
@ -41,26 +43,20 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
// Fixes
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 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("FixSawSoftlock"), 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("FixDungeonMinimapIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 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("FixDaruniaDanceSpeed"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CreditsFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RedGanonBlood"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PulsateBossIcon"), 1),
// Difficulty
// NONE
@ -78,42 +74,33 @@ const std::vector<PresetEntry> vanillaPlusPresetEntries = {
const std::vector<PresetEntry> enhancedPresetEntries = {
// Quality of Life
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseWarp"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseWarp"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NoInputForCredits"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableCritWiggle"), 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("DisableCritWiggle"), 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("TimeSavers.SleepingWaterfall"), 1),
// Skips & Speed-ups
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipText"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SlowTextSpeed"), 5),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5),
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("SkipSwimDeepEndAnim"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 3),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FasterBlockPush"), 5), 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("SkulltulaFreeze"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipSaveConfirmation"), 1),
// Graphics
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableLOD"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PauseMenuAnimatedLink"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ShowDoorLocksOnBothSides"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ToTMedallionsColors"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("RememberMapToggleState"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("VisualAgony"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DynamicWalletIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterAmmoRendering"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TimeFlowFileSelect"), 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("FastOcarinaPlayback"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_FAST),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PersistentMasks"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("PersistentMasks"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NutsExplodeBombs"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DisableFirstPersonChus"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterBombchuShopping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SeparateArrows"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SkipArrowAnimation"), 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("SkipArrowAnimation"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastBoomerang"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterFarore"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FastFarores"), 1),
// Fixes
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GravediggingTourFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixFloorSwitches"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixZoraHintDialogue"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixVineFall"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixSawSoftlock"), 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("FixSawSoftlock"), 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("FixDungeonMinimapIcon"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("TwoHandedIdle"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NaviTextFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixTexturesOOB"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixEyesOpenWhileSleeping"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixHammerHand"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SceneSpecificDirtPathFix"), ZFIGHT_FIX_CONSISTENT_VANISH),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 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("HoverFishing"), 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),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("FixDaruniaDanceSpeed"), 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("HoverFishing"), 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
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnableBombchuDrops"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("EnableBombchuDrops"), 1), PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeWin"), 1),
// Minigames
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("SheikLAHint"), 0),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GregHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SariaHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FrogsHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MalonHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("HBAHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MerchantText"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("40GSHint"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("FullWallets"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),

View file

@ -47,7 +47,8 @@ void DrawPresetSelector(PresetType presetTypeId) {
const PresetDefinition selectedPresetDef = presetTypeDef.presets.at(selectedPresetId);
std::string comboboxTooltip = "";
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);
}

View file

@ -33,10 +33,13 @@ void OnEnMThunderInitReplaceUpdateWithCustom(void* thunder) {
#define CVAR_REMOVESPINATTACKDARKNESS_NAME CVAR_ENHANCEMENT("RemoveSpinAttackDarkness")
#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() {
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 });

View file

@ -100,9 +100,11 @@ void HandleRBAInventoryQuestItems(uint8_t itemToPutInBottle) {
auto itemOnCRight = gSaveContext.equips.buttonItems[3];
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) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 16) | (gSaveContext.inventory.questItems & 0xFF00FFFF);
gSaveContext.inventory.questItems =
(itemToPutInBottle << 16) | (gSaveContext.inventory.questItems & 0xFF00FFFF);
} else if (itemOnCRight == ITEM_SAW) {
gSaveContext.inventory.questItems = (itemToPutInBottle << 8) | (gSaveContext.inventory.questItems & 0xFFFF00FF);
} else if (itemOnCRight == ITEM_SWORD_BROKEN) {
@ -265,88 +267,115 @@ void HandleRBASceneFlags(uint8_t itemToPutInBottle) {
u32 scene = offset / sizeof(SavedSceneFlags);
switch (offset % sizeof(SavedSceneFlags)) {
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;
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;
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;
case 3:
gSaveContext.sceneFlags[scene].chest = itemToPutInBottle | (gSaveContext.sceneFlags[scene].chest & 0xFFFFFF00);
gSaveContext.sceneFlags[scene].chest =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].chest & 0xFFFFFF00);
break;
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;
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;
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;
case 7:
gSaveContext.sceneFlags[scene].swch = itemToPutInBottle | (gSaveContext.sceneFlags[scene].swch & 0xFFFFFF00);
gSaveContext.sceneFlags[scene].swch =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].swch & 0xFFFFFF00);
break;
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;
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;
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;
case 11:
gSaveContext.sceneFlags[scene].clear = itemToPutInBottle | (gSaveContext.sceneFlags[scene].clear & 0xFFFFFF00);
gSaveContext.sceneFlags[scene].clear =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].clear & 0xFFFFFF00);
break;
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;
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;
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;
case 15:
gSaveContext.sceneFlags[scene].collect = itemToPutInBottle | (gSaveContext.sceneFlags[scene].collect & 0xFFFFFF00);
gSaveContext.sceneFlags[scene].collect =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].collect & 0xFFFFFF00);
break;
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;
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;
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;
case 19:
gSaveContext.sceneFlags[scene].unk = itemToPutInBottle | (gSaveContext.sceneFlags[scene].unk & 0xFFFFFF00);
break;
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;
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;
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;
case 23:
gSaveContext.sceneFlags[scene].rooms = itemToPutInBottle | (gSaveContext.sceneFlags[scene].rooms & 0xFFFFFF00);
gSaveContext.sceneFlags[scene].rooms =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].rooms & 0xFFFFFF00);
break;
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;
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;
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;
case 27:
gSaveContext.sceneFlags[scene].floors = itemToPutInBottle | (gSaveContext.sceneFlags[scene].floors & 0xFFFFFF00);
gSaveContext.sceneFlags[scene].floors =
itemToPutInBottle | (gSaveContext.sceneFlags[scene].floors & 0xFFFFFF00);
break;
}
}

View file

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

View file

@ -247,13 +247,17 @@ static void TimeDisplayInitTimers() {
}
void TimeDisplayWindow::InitElement() {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("GAMEPLAY_TIMER", gClockIconTex, 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("GAMEPLAY_TIMER", gClockIconTex,
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));
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();

View file

@ -20,16 +20,16 @@ void FasterHeavyBlockLift_Register() {
REGISTER_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, {
Actor* actor = va_arg(args, Actor*);
if (
actor->id == ACTOR_BG_HEAVY_BLOCK &&
(CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO))
) {
if (actor->id == ACTOR_BG_HEAVY_BLOCK &&
(CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO))) {
*should = false;
}
});
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;
}
});
@ -42,7 +42,8 @@ void FasterHeavyBlockLift_Register() {
// 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;
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;
LinkAnimation_PlayOnceSetSpeed(gPlayState, &player->skelAnime, anim, 5.0f);
}

View file

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

View file

@ -38,15 +38,18 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP;
isBlueWarpCutscene = true;
// 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;
isBlueWarpCutscene = true;
// 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;
isBlueWarpCutscene = true;
// 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
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT);
@ -58,14 +61,16 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
isBlueWarpCutscene = true;
// 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
Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED);
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = true;
// 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
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800;
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;
isBlueWarpCutscene = true;
// 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;
isBlueWarpCutscene = true;
// 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;
isBlueWarpCutscene = true;
}
@ -92,7 +99,8 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
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) {
Entrance_OverrideBlueWarp();
}
@ -142,31 +150,35 @@ void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) {
void SkipBlueWarp_OnActorUpdate(void* actorPtr) {
EnKo* enKo = static_cast<EnKo*>(actorPtr);
if (
(enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 &&
enKo->actionFunc == func_80A995CC &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)
) {
if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && enKo->actionFunc == func_80A995CC &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
enKo->actionFunc = EnKo_MoveWhenReady;
}
}
/**
* 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) {
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);
}
}
}
void SkipBlueWarp_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO, SkipBlueWarp_OnActorUpdate);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS);
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);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO,
SkipBlueWarp_OnActorUpdate);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_GIVE_ITEM_FROM_BLUE_WARP,
SkipBlueWarp_ShouldGiveItem);
}

View file

@ -14,7 +14,8 @@ void SkipDekuTreeIntro_Register() {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
BgTreemouth* treeMouth = va_arg(args, BgTreemouth*);
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);
*should = false;
}

View file

@ -11,11 +11,13 @@ extern "C" {
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, {
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);
if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true)) {
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
* that they received the item when skipping the cutscene, so we'll prevent it, and queue it up to be given instead.
* 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 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, {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {

View file

@ -21,7 +21,8 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
Audio_PlayFanfare(NA_BGM_APPEAR);
enZl4->csState = 8; // ZL4_CS_PLAN
} 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);
if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) {
@ -34,12 +35,14 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
void SkipToGivingZeldasLetter_OnActorInit(void* actorPtr) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
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;
}
}
void SkipToGivingZeldasLetter_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_ZL4, SkipToGivingZeldasLetter_OnActorInit);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_ZL4,
SkipToGivingZeldasLetter_OnActorInit);
}

View file

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

View file

@ -17,13 +17,10 @@ extern "C" {
*/
void MoveMidoInKokiriForest_Register() {
REGISTER_VB_SHOULD(VB_MOVE_MIDO_IN_KOKIRI_FOREST, {
if (
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) &&
gSaveContext.cutsceneIndex == 0
) {
(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && gSaveContext.cutsceneIndex == 0) {
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
*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, {
EnRu1* enRu1 = va_arg(args, EnRu1*);
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
// 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.
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;
}
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) {
EnRu1* enRu1 = static_cast<EnRu1*>(actorRef);
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {

View file

@ -11,7 +11,11 @@
#include <filesystem>
#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() {
// clang-format off
@ -357,8 +361,11 @@ void AudioCollection::AddToCollection(char* otrPath, uint16_t seqNum) {
}
SequenceInfo info = { seqNum,
sequenceName,
StringHelper::Replace(StringHelper::Replace(StringHelper::Replace(sequenceName, " ", "_"), "~", "-"),".", ""),
type, false, true};
StringHelper::Replace(
StringHelper::Replace(StringHelper::Replace(sequenceName, " ", "_"), "~", "-"), ".", ""),
type,
false,
true };
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
// play the normal track as usual.
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;
}
}
@ -402,10 +410,12 @@ void AudioCollection::AddToShufflePool(SequenceInfo* seqInfo) {
}
void AudioCollection::InitializeShufflePool() {
if (shufflePoolInitialized) return;
if (shufflePoolInitialized)
return;
for (auto& [seqId, seqInfo] : sequenceMap) {
if (!seqInfo.canBeUsedAsReplacement) continue;
if (!seqInfo.canBeUsedAsReplacement)
continue;
const std::string cvarKey = std::string(CVAR_AUDIO("Excluded.")) + seqInfo.sfxKey;
if (CVarGetInteger(cvarKey.c_str(), 0)) {
excludedSequences.insert(&seqInfo);

View file

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

View file

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

View file

@ -12,8 +12,7 @@
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
void BootCommands_Init()
{
void BootCommands_Init() {
// 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("NewSeedGenerated"));

View file

@ -28,17 +28,14 @@ typedef struct BossRushSetting {
} BossRushSetting;
BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = {
{
{ "BOSSES:", "BOSSE:", "BOSS:" },
{ { "BOSSES:", "BOSSE:", "BOSS:" },
{
{ "All", "Alle", "Tous" },
{ "Child", "Kind", "Enfant" },
{ "Adult", "Erwachsener", "Adulte" },
{ "Ganondorf & Ganon", "Ganondorf & Ganon", "Ganondorf & Ganon" },
}
},
{
{ "HEARTS:", "HERZEN:", "COEURS:" },
} },
{ { "HEARTS:", "HERZEN:", "COEURS:" },
{
{ "10", "10", "10" },
{ "15", "15", "15" },
@ -46,47 +43,35 @@ BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = {
{ "3", "3", "3" },
{ "5", "5", "5" },
{ "7", "7", "7" },
}
},
{
{ "AMMO:", "MUNITION:", "MUNITIONS:" },
} },
{ { "AMMO:", "MUNITION:", "MUNITIONS:" },
{
{ "Limited", "Limitiert", "Limitées" },
{ "Full", "Voll", "Pleines" },
{ "Maxed", "Maximum", "Maximum" },
}
},
{
{ "HEAL:", "REGENERATION:", "SOIN:" },
} },
{ { "HEAL:", "REGENERATION:", "SOIN:" },
{
{ "Before Ganondorf", "Vor Ganondorf", "Avant Ganondorf" },
{ "Every Boss", "Bei jedem Boss", "Tous les Boss" },
{ "Never", "Niemals", "Jamais" },
}
},
{
{ "HYPER BOSSES:", "HYPER-BOSSE:", "HYPER BOSS:" },
} },
{ { "HYPER BOSSES:", "HYPER-BOSSE:", "HYPER BOSS:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "MAGIC:", "MAGIE:", "MAGIE:" },
} },
{ { "MAGIC:", "MAGIE:", "MAGIE:" },
{
{ "Single", "Einzel", "Simple" },
{ "Double", "Doppel", "Double" },
}
},
{
{ "BIG. SWORD:", "BIG.-SCHWERT:", "EPÉE DE BIG.:" },
} },
{ { "BIG. SWORD:", "BIG.-SCHWERT:", "EPÉE DE BIG.:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "BOTTLE:", "FLASCHEN:", "BOUTEILLE:" },
} },
{ { "BOTTLE:", "FLASCHEN:", "BOUTEILLE:" },
{
{ "No", "Nein", "Non" },
{ "Empty", "Leer", "Vide" },
@ -94,36 +79,27 @@ BossRushSetting BossRushOptions[BR_OPTIONS_MAX] = {
{ "Red Potion", "Rotes Elixier", "Potion Rouge" },
{ "Green Potion", "Grünes Elixier", "Potion Verte" },
{ "Blue Potion", "Blaues Elixier", "Potion Bleue" },
}
},
{
{ "LONGSHOT:", "ENTERHAKEN:", "SUPER GRAPPIN:" },
} },
{ { "LONGSHOT:", "ENTERHAKEN:", "SUPER GRAPPIN:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "HOVER BOOTS:", "GLEITSTIEFEL:", "BOTTES DES AIRS:" },
} },
{ { "HOVER BOOTS:", "GLEITSTIEFEL:", "BOTTES DES AIRS:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "BUNNY HOOD:", "HASENOHREN:", "MASQUE DU LAPIN:" },
} },
{ { "BUNNY HOOD:", "HASENOHREN:", "MASQUE DU LAPIN:" },
{
{ "No", "Nein", "Non" },
{ "Yes", "Ja", "Oui" },
}
},
{
{ "TIMER:", "TIMER:", "TIMER:" },
} },
{ { "TIMER:", "TIMER:", "TIMER:" },
{
{ "Yes", "Ja", "Oui" },
{ "No", "Nein", "Non" },
}
}
} }
};
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) {
play->nextEntranceIndex = ENTR_GANONDORF_BOSS_0;
} 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;
}
// 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);
}
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) {
gSaveContext.ship.stats.playTimer += 2;
gSaveContext.ship.stats.gameComplete = 1;
@ -399,17 +378,17 @@ void BossRush_InitSave() {
gSaveContext.eventChkInf[7] |= 0x80; // bongo bongo
// 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++) {
gSaveContext.ship.randomizerInf[i] = 0;
}
// Set items
std::array<u8, 24> brItems = {
ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE,
ITEM_SLINGSHOT, ITEM_NONE, ITEM_NONE, ITEM_HOOKSHOT, ITEM_NONE, ITEM_NONE,
ITEM_BOOMERANG, ITEM_LENS, ITEM_NONE, ITEM_HAMMER, ITEM_ARROW_LIGHT, ITEM_NONE,
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE,
ITEM_NONE, ITEM_HOOKSHOT, ITEM_NONE, ITEM_NONE, ITEM_BOOMERANG, ITEM_LENS, ITEM_NONE, ITEM_HAMMER,
ITEM_ARROW_LIGHT, 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) {
@ -541,11 +520,13 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
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;
}
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;
}
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;
}
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;
}
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;
}
case SCENE_WATER_TEMPLE_BOSS: {
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;
}
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;
}
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;
}
default: {
@ -699,12 +686,18 @@ void BossRush_RegisterHooks() {
onBossDefeatHook = 0;
onActorUpdate = 0;
if (!IS_BOSS_RUSH) return;
if (!IS_BOSS_RUSH)
return;
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(BossRush_OnVanillaBehaviorHandler);
onSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(BossRush_OnSceneInitHandler);
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);
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(
BossRush_OnVanillaBehaviorHandler);
onSceneInitHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(BossRush_OnSceneInitHandler);
onActorInitHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(BossRush_OnActorInitHandler);
onBossDefeatHook =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnBossDefeat>(BossRush_OnBossDefeatHandler);
onActorUpdate = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(
ACTOR_DOOR_WARP1, BossRush_OnBlueWarpUpdate);
});
}

View file

@ -20,15 +20,22 @@ static Color_RGBA8 textColorDefault = { 255, 255, 255, 255 };
static Color_RGBA8 range1ColorDefault = { 255, 178, 0, 255 };
static Color_RGBA8 range2ColorDefault = { 0, 255, 0, 255 };
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_PRESSED, "Shown Only While Pressed" }, { BUTTON_OUTLINE_ALWAYS_HIDDEN, "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*> buttonOutlineOptions = {
{ BUTTON_OUTLINE_ALWAYS_SHOWN, "Always Shown" },
{ BUTTON_OUTLINE_NOT_PRESSED, "Shown Only While Not Pressed" },
{ BUTTON_OUTLINE_PRESSED, "Shown Only While Pressed" },
{ BUTTON_OUTLINE_ALWAYS_HIDDEN, "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 =
{{ STICK_MODE_ALWAYS_SHOWN, "Always" }, { STICK_MODE_HIDDEN_IN_DEADZONE, "While In Use" }, { STICK_MODE_ALWAYS_HIDDEN, "Never" }};
static std::unordered_map<int32_t, const char*> stickModeOptions = { { STICK_MODE_ALWAYS_SHOWN, "Always" },
{ STICK_MODE_HIDDEN_IN_DEADZONE, "While In Use" },
{ STICK_MODE_ALWAYS_HIDDEN, "Never" } };
InputViewer::~InputViewer() {
SPDLOG_TRACE("destruct input viewer");
@ -68,66 +75,78 @@ void InputViewer::DrawElement() {
if (!sButtonTexturesLoaded) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"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("B-Btn", "textures/buttons/BBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn",
"textures/buttons/StartBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick",
"textures/buttons/AnalogStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left",
"textures/buttons/DPadLeft.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right",
"textures/buttons/DPadRight.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down",
"textures/buttons/DPadDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1", "textures/buttons/Mod1.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2", "textures/buttons/Mod2.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick",
"textures/buttons/RightStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline",
"textures/buttons/ABtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn Outline",
"textures/buttons/BBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn Outline",
"textures/buttons/LBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn Outline",
"textures/buttons/RBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn Outline",
"textures/buttons/ZBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn Outline",
"textures/buttons/StartBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left Outline",
"textures/buttons/CLeftOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right Outline",
"textures/buttons/CRightOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up Outline",
"textures/buttons/CUpOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down Outline",
"textures/buttons/CDownOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick Outline",
"textures/buttons/AnalogStickOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("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");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn",
"textures/buttons/ABtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn",
"textures/buttons/BBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn",
"textures/buttons/LBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn",
"textures/buttons/RBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn",
"textures/buttons/ZBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Start-Btn", "textures/buttons/StartBtn.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left",
"textures/buttons/CLeft.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right",
"textures/buttons/CRight.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up",
"textures/buttons/CUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down",
"textures/buttons/CDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Analog-Stick", "textures/buttons/AnalogStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Left", "textures/buttons/DPadLeft.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Right", "textures/buttons/DPadRight.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up",
"textures/buttons/DPadUp.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Dpad-Down", "textures/buttons/DPadDown.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1",
"textures/buttons/Mod1.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2",
"textures/buttons/Mod2.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Right-Stick", "textures/buttons/RightStick.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"A-Btn Outline", "textures/buttons/ABtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"B-Btn Outline", "textures/buttons/BBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"L-Btn Outline", "textures/buttons/LBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"R-Btn Outline", "textures/buttons/RBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Z-Btn Outline", "textures/buttons/ZBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Start-Btn Outline", "textures/buttons/StartBtnOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"C-Left Outline", "textures/buttons/CLeftOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"C-Right Outline", "textures/buttons/CRightOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"C-Up Outline", "textures/buttons/CUpOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"C-Down Outline", "textures/buttons/CDownOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"Analog-Stick Outline", "textures/buttons/AnalogStickOutline.png");
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage(
"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;
}
@ -140,7 +159,8 @@ void InputViewer::DrawElement() {
const float scale = CVarGetFloat(CVAR_INPUT_VIEWER("Scale"), 1.0f);
#endif
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);
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::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_NoResize | ImGuiWindowFlags_NoBackground |
@ -266,9 +287,9 @@ void InputViewer::DrawElement() {
ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos);
RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize,
useGlobalOutlineMode
? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED));
useGlobalOutlineMode ? buttonOutlineMode
: CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"),
BUTTON_OUTLINE_NOT_PRESSED));
}
// Dpad
@ -371,7 +392,8 @@ void InputViewer::DrawElement() {
// Analog stick angle text
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));
// Scale font with input viewer scale
float oldFontScale = ImGui::GetFont()->Scale;
@ -392,17 +414,16 @@ void InputViewer::DrawElement() {
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Enabled"), 0) &&
(rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) {
ImGui::PushStyleColor(
ImGuiCol_Text,
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"), range1ColorDefault)));
}
else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) &&
ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color.Value"),
range1ColorDefault)));
} else if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0) &&
(rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) {
ImGui::PushStyleColor(
ImGuiCol_Text,
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"), range2ColorDefault)));
}
else {
ImGui::PushStyleColor(ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"),
ImGuiCol_Text, VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color.Value"),
range2ColorDefault)));
} else {
ImGui::PushStyleColor(ImGuiCol_Text,
VecFromRGBA8(CVarGetColor(CVAR_INPUT_VIEWER("AnalogAngles.TextColor.Value"),
textColorDefault)));
}
@ -430,15 +451,23 @@ InputViewerSettingsWindow::~InputViewerSettingsWindow() {
void InputViewerSettingsWindow::DrawElement() {
// gInputViewer.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
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);
// 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);
@ -446,21 +475,26 @@ void InputViewerSettingsWindow::DrawElement() {
if (ImGui::CollapsingHeader("Buttons")) {
// gInputViewer.ButtonOutlineMode
CVarCombobox("Button Outlines/Backgrounds", CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions,
ComboboxOptions({{ .disabled = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1), .disabledTooltip = "Disabled because Global Button Outline is off" }})
.Color(THEME_COLOR).DefaultIndex(BUTTON_OUTLINE_NOT_PRESSED)
CVarCombobox(
"Button Outlines/Backgrounds", CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions,
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 "
"custom input viewers."));
// 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();
bool useIndividualOutlines = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1);
// 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)) {
ImGui::Indent();
CVarCombobox("##ABtnOutline", CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -468,7 +502,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##BBtnOutline", CVAR_INPUT_VIEWER("BBtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -476,7 +511,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##CUpOutline", CVAR_INPUT_VIEWER("CUpOutlineMode"), buttonOutlineOptionsVerbose,
@ -484,7 +520,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##CRightOutline", CVAR_INPUT_VIEWER("CRightOutlineMode"), buttonOutlineOptionsVerbose,
@ -492,7 +529,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##CDownOutline", CVAR_INPUT_VIEWER("CDownOutlineMode"), buttonOutlineOptionsVerbose,
@ -500,7 +538,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##CLeftOutline", CVAR_INPUT_VIEWER("CLeftOutlineMode"), buttonOutlineOptionsVerbose,
@ -508,7 +547,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##LBtnOutline", CVAR_INPUT_VIEWER("LBtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -516,7 +556,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##RBtnOutline", CVAR_INPUT_VIEWER("RBtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -524,7 +565,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##ZBtnOutline", CVAR_INPUT_VIEWER("ZBtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -532,7 +574,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##StartBtnOutline", CVAR_INPUT_VIEWER("StartBtnOutlineMode"), buttonOutlineOptionsVerbose,
@ -540,7 +583,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##DpadOutline", CVAR_INPUT_VIEWER("DpadOutlineMode"), buttonOutlineOptionsVerbose,
@ -548,7 +592,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##Mmod1Outline", CVAR_INPUT_VIEWER("Mod1OutlineMode"), buttonOutlineOptionsVerbose,
@ -556,7 +601,8 @@ void InputViewerSettingsWindow::DrawElement() {
ImGui::Unindent();
}
// 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)) {
ImGui::Indent();
CVarCombobox("##Mod2Outline", CVAR_INPUT_VIEWER("Mod2OutlineMode"), buttonOutlineOptionsVerbose,
@ -569,72 +615,124 @@ void InputViewerSettingsWindow::DrawElement() {
if (ImGui::CollapsingHeader("Analog Stick")) {
// gInputViewer.AnalogStick.VisibilityMode
CVarCombobox("Analog Stick Visibility", CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions,
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."));
CVarCombobox(
"Analog Stick Visibility", CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), stickModeOptions,
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
CVarCombobox("Analog Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), stickModeOptions,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip("Determines the conditions under which the analog stick outline/background texture is visible."));
CVarCombobox(
"Analog Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"),
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
CVarSliderInt("Analog Stick Movement: %dpx", CVAR_INPUT_VIEWER("AnalogStick.Movement"), 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."));
CVarSliderInt("Analog Stick Movement: %dpx", CVAR_INPUT_VIEWER("AnalogStick.Movement"),
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);
}
if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) {
// gInputViewer.RightStick.VisibilityMode
CVarCombobox("Right Stick Visibility", CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions,
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."));
CVarCombobox(
"Right Stick Visibility", CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), stickModeOptions,
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
CVarCombobox("Right Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions,
ComboboxOptions().Color(THEME_COLOR).DefaultIndex(STICK_MODE_ALWAYS_SHOWN)
.Tooltip("Determines the conditions under which the right stick outline/background texture is visible."));
CVarCombobox(
"Right Stick Outline/Background Visibility", CVAR_INPUT_VIEWER("RightStick.OutlineMode"), stickModeOptions,
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
CVarSliderInt("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."));
CVarSliderInt(
"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);
}
if (ImGui::CollapsingHeader("Analog Angle Values")) {
// gAnalogAngles
CVarCheckbox("Show Analog Stick Angle Values", CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), CheckboxOptions().Color(THEME_COLOR)
.Tooltip("Displays analog stick angle values in the input viewer"));
CVarCheckbox(
"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)) {
// gInputViewer.AnalogAngles.TextColor
CVarColorPicker("Text Color", CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), textColorDefault,
true, ColorPickerRandomButton | ColorPickerResetButton);
CVarColorPicker("Text Color", CVAR_INPUT_VIEWER("AnalogAngles.TextColor"), textColorDefault, true,
ColorPickerRandomButton | ColorPickerResetButton);
// gAnalogAngleScale
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
CVarSliderInt("Angle Text Offset: %dpx", CVAR_INPUT_VIEWER("AnalogAngles.Offset"), 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."));
CVarSliderInt("Angle Text Offset: %dpx", CVAR_INPUT_VIEWER("AnalogAngles.Offset"),
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);
// gInputViewer.AnalogAngles.Range1.Enabled
CVarCheckbox("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)"));
CVarCheckbox(
"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)) {
// gInputViewer.AnalogAngles.Range1.Color
CVarColorPicker("ESS Color", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), range1ColorDefault,
true, ColorPickerRandomButton | ColorPickerResetButton);
CVarColorPicker("ESS Color", CVAR_INPUT_VIEWER("AnalogAngles.Range1.Color"), range1ColorDefault, true,
ColorPickerRandomButton | ColorPickerResetButton);
}
UIWidgets::PaddedSeparator(true, true);
// 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 "
"produce a walking speed (on flat ground)\n\n"
"Useful for 1.0 Empty Jumpslash Quick Put Away"));
if (CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range2.Enabled"), 0)) {
// gInputViewer.AnalogAngles.Range2.Color
CVarColorPicker("Walking Speed Color", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"), range2ColorDefault,
true, ColorPickerRandomButton | ColorPickerResetButton);
CVarColorPicker("Walking Speed Color", CVAR_INPUT_VIEWER("AnalogAngles.Range2.Color"),
range2ColorDefault, true, ColorPickerRandomButton | ColorPickerResetButton);
}
}
}

View file

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

View file

@ -26,13 +26,9 @@ void SohInputEditorWindow::InitElement() {
mButtonsBitmasks = { BTN_A, BTN_B, BTN_START, BTN_L, BTN_R, BTN_Z, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT };
mDpadBitmasks = { BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT };
mModifierButtonsBitmasks = { BTN_CUSTOM_MODIFIER1, BTN_CUSTOM_MODIFIER2 };
mCustomOcarinaButtonsBitmasks = {
BTN_CUSTOM_OCARINA_NOTE_D4,
BTN_CUSTOM_OCARINA_NOTE_F4,
BTN_CUSTOM_OCARINA_NOTE_A4,
BTN_CUSTOM_OCARINA_NOTE_B4,
BTN_CUSTOM_OCARINA_NOTE_D5
};
mCustomOcarinaButtonsBitmasks = { BTN_CUSTOM_OCARINA_NOTE_D4, BTN_CUSTOM_OCARINA_NOTE_F4,
BTN_CUSTOM_OCARINA_NOTE_A4, BTN_CUSTOM_OCARINA_NOTE_B4,
BTN_CUSTOM_OCARINA_NOTE_D5 };
addButtonName(BTN_A, "A");
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::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
if (ImGui::SliderInt(StringHelper::Sprintf("##Sensitivity%d", id).c_str(), &sensitivityPercentage, 0, 200, "%d%%",
ImGuiSliderFlags_AlwaysClamp)) {
if (ImGui::SliderInt(StringHelper::Sprintf("##Sensitivity%d", id).c_str(), &sensitivityPercentage, 0, 200,
"%d%%", ImGuiSliderFlags_AlwaysClamp)) {
controllerStick->SetSensitivity(sensitivityPercentage);
}
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 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 "
"health < 40%. Green otherwise.\n\n"
"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");
}
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."));
CVarCheckbox("Critical Health Override", CVAR_SETTING("LEDCriticalOverride"),
CheckboxOptions({{ .disabled = CVarGetInteger(CVAR_SETTING("LEDColorSource"), 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."));
CVarCheckbox(
"Critical Health Override", CVAR_SETTING("LEDCriticalOverride"),
CheckboxOptions({ { .disabled = CVarGetInteger(CVAR_SETTING("LEDColorSource"),
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();
}
@ -1234,12 +1243,9 @@ void SohInputEditorWindow::DrawGyroSection(uint8_t port) {
}
}
const ImGuiTableFlags PANEL_TABLE_FLAGS =
ImGuiTableFlags_BordersH |
ImGuiTableFlags_BordersV;
const ImGuiTableFlags PANEL_TABLE_FLAGS = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV;
const ImGuiTableColumnFlags PANEL_TABLE_COLUMN_FLAGS =
ImGuiTableColumnFlags_IndentEnable |
ImGuiTableColumnFlags_NoSort;
ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
namespace TableHelper {
void InitHeader(bool has_header = true) {
@ -1264,7 +1270,7 @@ namespace TableHelper {
ImGui::AlignTextToFramePadding();
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
}
} // namespace TableHelper
void SohInputEditorWindow::addButtonName(N64ButtonMask mask, const char* name) {
buttons.push_back(std::make_pair(mask, name));
@ -1344,29 +1350,47 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() {
void SohInputEditorWindow::DrawCameraControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
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), "
"aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)"));
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"));
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"));
}
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"));
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"));
CVarCheckbox("Invert Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingXAxis"), 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)
.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 Shield Aiming X Axis", CVAR_SETTING("Controls.InvertShieldAimingXAxis"),
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).Tooltip("Inverts the Shield Aiming Y Axis"));
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"));
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"));
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)) {
CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.X"));
CVarClear(CVAR_SETTING("FirstPersonCameraSensitivity.Y"));
@ -1374,10 +1398,24 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
}
}
if (CVarGetInteger(CVAR_SETTING("FirstPersonCameraSensitivity.Enabled"), 0)) {
CVarSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%", CVAR_SETTING("FirstPersonCameraSensitivity.X"),
FloatSliderOptions().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));
CVarSliderFloat("Aiming/First-Person Horizontal Sensitivity: %.0f %%",
CVAR_SETTING("FirstPersonCameraSensitivity.X"),
FloatSliderOptions()
.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);
@ -1385,19 +1423,37 @@ void SohInputEditorWindow::DrawCameraControlPanel() {
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
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 "
"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)
.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)
.Tooltip("Inverts the Camera Y Axis in:\n-Free look"));
CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"),
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).Tooltip("Inverts the Camera Y Axis in:\n-Free look"));
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"),
FloatSliderOptions().Color(THEME_COLOR).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));
FloatSliderOptions()
.Color(THEME_COLOR)
.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);
}
@ -1405,16 +1461,25 @@ void SohInputEditorWindow::DrawDpadControlPanel() {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail());
CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"), CheckboxOptions().Color(THEME_COLOR)
.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"));
CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"),
CheckboxOptions()
.Color(THEME_COLOR)
.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)) {
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"));
if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) {
@ -1536,24 +1601,52 @@ void SohInputEditorWindow::DrawLinkTab() {
DrawButtonLine("M2", portIndex, BTN_CUSTOM_MODIFIER2);
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"));
if (CVarGetInteger(CVAR_SETTING("WalkModifier.Enabled"), 0)) {
UIWidgets::Spacer(5);
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());
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"),
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"),
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::BeginGroupPanel("Swim Modifier", ImGui::GetContentRegionAvail());
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"),
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);
}
@ -1755,7 +1848,8 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) {
}
PopStyleButton();
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);
if (ImGui::Button("Cancel")) {
shouldClose = true;

View file

@ -41,7 +41,8 @@ class SohInputEditorWindow : public Ship::GuiWindow {
void DrawButtonLineEditMappingButton(uint8_t port, N64ButtonMask bitmask, std::string id);
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 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
#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
// every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in `DrawCosmeticsEditor`
// Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to
// 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 {
COSMETICS_GROUP_LINK,
COSMETICS_GROUP_MIRRORSHIELD,
@ -50,7 +51,8 @@ typedef struct {
static float TablesCellsWidth = 300.0f;
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_RandomizeGroup(CosmeticGroup group);

View file

@ -70,7 +70,8 @@ extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToD
gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, PRIMITIVE, ENV_ALPHA, TEXEL0, 0, 0, 0, TEXEL0, PRIMITIVE, ENVIRONMENT,
COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 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);
gDPSetEnvColor(POLY_OPA_DISP++, nintendoLogoColor.r, nintendoLogoColor.g, nintendoLogoColor.b, 128);
} 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,
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)
{
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,
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);
for (idx = 0, y = 94; idx < 16; idx++, y += 2) {
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, 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,
(2 - 1) << G_TEXTURE_IMAGE_FRAC);
gDPSetTileSize(POLY_OPA_DISP++, 0, 0, 0, (192 - 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);
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;
gSPSegment(POLY_OPA_DISP++, 0x08,
(uintptr_t)Gfx_TwoTexScroll(titleContext->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1,
0, (1 * -2) % 128, 32, 32));
(uintptr_t)Gfx_TwoTexScroll(titleContext->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1, 0,
(1 * -2) % 128, 32, 32));
Matrix_Translate(0.0f, -10.0f, 0.0f, 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);
ResourceMgr_PatchGfxByName(gLinkAdultMirrorShieldSwordAndSheathFarDL, patchName.c_str(), i, gsDPNoOp());
}
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathNearDL, "adultNoMSHylianShield1", 75, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathFarDL, "adultNoMSHylianShield2", 71, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathNearDL, "adultNoMasterSword1", 2, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathNearDL, "adultNoMSHylianShield1", 75,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHylianShieldSwordAndSheathFarDL, "adultNoMSHylianShield2", 71,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathNearDL, "adultNoMasterSword1", 2,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultMasterSwordAndSheathFarDL, "adultNoMasterSword2", 2, gsSPEndDisplayList());
} else {
// Unpatching if conditions are not met
@ -86,7 +89,8 @@ void RegisterNoMasterSword() {
int32_t startMode = va_arg(args, int32_t);
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
*should = false;

View file

@ -19,10 +19,8 @@ typedef struct {
} DListPatchInfo;
static DListPatchInfo freezardBodyDListPatchInfos[] = {
{ gFreezardIntactDL, 5 },
{ gFreezardTopRightHornChippedDL, 5 },
{ gFreezardHeadChippedDL, 5 },
{ gFreezardIceTriangleDL, 5 },
{ gFreezardIntactDL, 5 }, { gFreezardTopRightHornChippedDL, 5 },
{ gFreezardHeadChippedDL, 5 }, { gFreezardIceTriangleDL, 5 },
{ gFreezardIceRockDL, 5 },
};
@ -339,7 +337,8 @@ void PatchMirroredSoldOutGI() {
void PatchMirroredSunSongEtching() {
// 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 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;
@ -365,7 +364,8 @@ void PatchMirroredSunSongEtching() {
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTexture_1", 13, mirroredSunSongTex[1]);
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
ResourceMgr_PatchGfxByName(gRoyalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_2", 25, gsSPNoOp());
} else {

View file

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

View file

@ -41,10 +41,13 @@ class CustomMessage {
CustomMessage() = default;
CustomMessage(std::string english_, std::string german_, std::string french_,
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);
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);
static CustomMessage LoadVanillaMessageTableEntry(uint16_t textId);

View file

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

View file

@ -29,7 +29,8 @@ void MessageViewer::DrawElement() {
ImGui::Text("Table ID");
ImGui::SameLine();
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");
ImGui::Text("Text ID");
ImGui::SameLine();
@ -41,7 +42,8 @@ void MessageViewer::DrawElement() {
case HEXADECIMAL:
default:
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;
}
PopStyleInput();
@ -169,8 +171,7 @@ void FindMessage(PlayState* play, const uint16_t textId, const uint8_t language)
font->msgLength = nextSeg - foundSeg;
}
static const char* msgStaticTbl[] =
{
static const char* msgStaticTbl[] = {
gDefaultMessageBackgroundTex,
gSignMessageBackgroundTex,
gNoteStaffMessageBackgroundTex,
@ -207,7 +208,8 @@ void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t lan
const CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(tableId, textId);
font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition();
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);
}
@ -261,5 +263,3 @@ void MessageDebug_DisplayCustomMessage(const char* customMessage) {
CustomMessage(customMessage, customMessage, customMessage));
MessageDebug_StartTextBox(MessageViewer::TABLE_ID, 0, 0);
}

View file

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

View file

@ -46,18 +46,12 @@ typedef enum {
} RetrievalMethod;
std::array<const char*, 12> acMapping = {
"Switch",
"Background (Prop type 1)",
"Player",
"Bomb",
"NPC",
"Enemy",
"Prop type 2",
"Item/Action",
"Misc.",
"Boss",
"Door",
"Chest",
"Switch", "Background (Prop type 1)",
"Player", "Bomb",
"NPC", "Enemy",
"Prop type 2", "Item/Action",
"Misc.", "Boss",
"Door", "Chest",
};
using namespace UIWidgets;
@ -76,7 +70,8 @@ const std::string GetActorDescription(u16 id) {
template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) {
// First group encapsulates the inner portion and border
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
ImGui::BeginGroup();
@ -376,33 +371,11 @@ void CreateActorSpecificData() {
}
static const char* items[] = {
"Green Rupee",
"Blue Rupee",
"Red Rupee",
"Recovery Heart",
"Bombs (A)",
"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",
"Green Rupee", "Blue Rupee", "Red Rupee", "Recovery Heart", "Bombs (A)", "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;
@ -413,33 +386,11 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_OBJ_COMB] = [](s16 params) -> s16 {
static const char* items[] = {
"Green Rupee",
"Blue Rupee",
"Red Rupee",
"Recovery Heart",
"Bombs (A)",
"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",
"Green Rupee", "Blue Rupee", "Red Rupee", "Recovery Heart", "Bombs (A)", "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;
@ -580,14 +531,7 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_EN_ELF] = [](s16 params) -> s16 {
static const char* items[] = {
"Navi",
"Revive Bottle",
"Heal Timed",
"Kokiri",
"Spawner",
"Revive Death",
"Heal",
"Heal Big",
"Navi", "Revive Bottle", "Heal Timed", "Kokiri", "Spawner", "Revive Death", "Heal", "Heal Big",
};
int selectedItem = params;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
@ -636,18 +580,14 @@ void CreateActorSpecificData() {
actorSpecificData[ACTOR_DOOR_WARP1] = [](s16 params) -> s16 {
static const char* items[] = {
"Blue Crystal", // -2
"Dungeon Adult",
"Dungeon Child",
"Dungeon Adult", "Dungeon Child",
"Clear Flag", // Activate on temp clear flag
"Sages", // Used by sages warping into chamber of sages during their cutscene
"Purple Crystal",
"Yellow", // The colored variants don't warp, they are cutscene setpieces
"Blue Ruto",
"Destination", // Spawning in after having taken a warp
"UNK 7",
"Orange",
"Green",
"Red",
"UNK 7", "Orange", "Green", "Red",
};
int selectedItem = params + 2;
if (ImGui::Combo("Type", &selectedItem, items, IM_ARRAYSIZE(items))) {
@ -819,11 +759,7 @@ void CreateActorSpecificData() {
};
actorSpecificData[ACTOR_EN_KUSA] = [](s16 params) -> s16 {
static const char* items[] = {
"0",
"1",
"2"
};
static const char* items[] = { "0", "1", "2" };
int type = params & 3;
ImGui::Combo("Type", &type, items, IM_ARRAYSIZE(items));
@ -845,12 +781,7 @@ void CreateActorSpecificData() {
};
actorSpecificData[ActorDB::Instance->RetrieveId("En_Partner")] = [](s16 params) -> s16 {
static const char* items[] = {
"Port 1",
"Port 2",
"Port 3",
"Port 4"
};
static const char* items[] = { "Port 1", "Port 2", "Port 3", "Port 4" };
int selectedItem = params;
if (ImGui::Combo("Controller Port", &selectedItem, items, IM_ARRAYSIZE(items))) {
return selectedItem;
@ -986,17 +917,20 @@ void ActorViewerWindow::DrawElement() {
PushStyleHeader(THEME_COLOR);
if (ImGui::TreeNode("Selected Actor")) {
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str());
ImGui::Text("Description: %s", GetActorDescription(display->id).c_str());
ImGui::Text("Category: %s", acMapping[display->category]);
ImGui::Text("ID: %d", display->id);
ImGui::Text("Parameters: %d", display->params);
}, "Selected Actor");
},
"Selected Actor");
ImGui::SameLine();
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR);
ImGui::Text("Actor Position");
@ -1005,9 +939,11 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("Z##CurPos", ImGuiDataType_Float, &display->world.pos.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "Actor Position");
},
"Actor Position");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
PushStyleInput(THEME_COLOR);
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
ImGui::Text("Actor Rotation");
@ -1016,7 +952,8 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("Z##CurRot", ImGuiDataType_S16, &display->world.rot.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "Actor Rotation");
},
"Actor Rotation");
if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) {
PushStyleInput(THEME_COLOR);
@ -1025,17 +962,21 @@ void ActorViewerWindow::DrawElement() {
UIWidgets::InsertHelpHoverText("Some actors might not use this!");
}
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("flags");
UIWidgets::DrawFlagArray32("flags", display->flags);
}, "flags");
},
"flags");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("bgCheckFlags");
UIWidgets::DrawFlagArray16("bgCheckFlags", display->bgCheckFlags);
}, "bgCheckFlags");
},
"bgCheckFlags");
if (Button("Refresh", ButtonOptions().Color(THEME_COLOR))) {
PopulateActorDropdown(category, list);
@ -1059,7 +1000,10 @@ void ActorViewerWindow::DrawElement() {
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);
fetch = player->talkActor;
if (fetch != NULL) {
@ -1069,7 +1013,8 @@ void ActorViewerWindow::DrawElement() {
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);
fetch = player->heldActor;
if (fetch != NULL) {
@ -1079,7 +1024,8 @@ void ActorViewerWindow::DrawElement() {
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);
fetch = player->interactRangeActor;
if (fetch != NULL) {
@ -1102,14 +1048,14 @@ void ActorViewerWindow::DrawElement() {
}
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);
if (ImGui::BeginCombo("Results", preview.c_str())) {
for (u8 i = 0; i < actors.size(); i++) {
if (ImGui::Selectable(
ActorDB::Instance->RetrieveEntry(actors[i]).desc.c_str(),
i == currentSelectedInDropdown
)) {
if (ImGui::Selectable(ActorDB::Instance->RetrieveEntry(actors[i]).desc.c_str(),
i == currentSelectedInDropdown)) {
currentSelectedInDropdown = i;
newActor.id = actors[i];
}
@ -1124,7 +1070,8 @@ void ActorViewerWindow::DrawElement() {
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)) {
PushStyleInput(THEME_COLOR);
@ -1137,16 +1084,19 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one);
PopStyleInput();
} else {
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Actor Specific Data");
newActor.params = actorSpecificData[newActor.id](newActor.params);
}, "Actor Specific Data");
},
"Actor Specific Data");
}
}
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
PushStyleInput(THEME_COLOR);
ImGui::Text("New Actor Position");
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
@ -1155,9 +1105,11 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("Z##NewPos", ImGuiDataType_Float, &newActor.pos.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "New Actor Position");
},
"New Actor Position");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
PushStyleInput(THEME_COLOR);
ImGui::Text("New Actor Rotation");
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
@ -1166,7 +1118,8 @@ void ActorViewerWindow::DrawElement() {
ImGui::InputScalar("Z##NewRot", ImGuiDataType_S16, &newActor.rot.z);
ImGui::PopItemWidth();
PopStyleInput();
}, "New Actor Rotation");
},
"New Actor Rotation");
if (Button("Fetch from Link", ButtonOptions().Color(THEME_COLOR))) {
Player* player = GET_PLAYER(gPlayState);
@ -1214,7 +1167,8 @@ void ActorViewerWindow::DrawElement() {
{ 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"))) {
NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG);
ActorViewer_AddTagForAllActors();

View file

@ -68,9 +68,11 @@ void ColViewerWindow::DrawElement() {
CVarCombobox("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.Waterbox"), ColRenderSettingNames, comboOpt);
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."));
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()
const std::string colorHelpText = "View and change the colors used for collision display.";
@ -78,38 +80,58 @@ void ColViewerWindow::DrawElement() {
if (ImGui::TreeNode("Colors")) {
UIWidgets::Tooltip(colorHelpText.c_str());
if (CVarColorPicker("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
scene_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }));
if (CVarColorPicker("Normal", CVAR_DEVELOPER_TOOLS("ColViewer.ColorNormal"), { 255, 255, 255, 255 }, false,
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)) {
hookshot_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }));
if (CVarColorPicker("Hookshot", CVAR_DEVELOPER_TOOLS("ColViewer.ColorHookshot"), { 128, 128, 255, 255 }, false,
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)) {
entrance_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }));
if (CVarColorPicker("Entrance", CVAR_DEVELOPER_TOOLS("ColViewer.ColorEntrance"), { 0, 255, 0, 255 }, false,
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)) {
specialSurface_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"), { 192, 255, 192, 255 }));
if (CVarColorPicker("Special Surface (Grass/Sand/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSpecialSurface"),
{ 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)) {
interactable_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"), { 192, 0, 192, 255 }));
if (CVarColorPicker("Interactable (Vines/Crawlspace/Etc)", CVAR_DEVELOPER_TOOLS("ColViewer.ColorInteractable"),
{ 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)) {
slope_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }));
if (CVarColorPicker("Slope", CVAR_DEVELOPER_TOOLS("ColViewer.ColorSlope"), { 255, 255, 128, 255 }, false,
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 }));
}
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 }));
}
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 }));
}
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 }));
}
if (CVarColorPicker("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }, false, ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
waterbox_col = VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }));
if (CVarColorPicker("Waterbox", CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }, false,
ColorPickerResetButton | ColorPickerRandomButton, THEME_COLOR)) {
waterbox_col =
VecFromRGBA8(CVarGetColor(CVAR_DEVELOPER_TOOLS("ColViewer.ColorWaterbox"), { 0, 0, 255, 255 }));
}
ImGui::TreePop();
@ -427,7 +449,8 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
// Draws the scene
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)) {
return;
@ -442,7 +465,8 @@ void DrawSceneCollision() {
// Draws all Bg Actors
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)) {
return;
}
@ -567,7 +591,8 @@ void DrawColCheckList(std::vector<Gfx>& dl, Collider** objects, int32_t count) {
// Draws all Col Check objects
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)) {
return;
}
@ -619,7 +644,8 @@ extern "C" f32 zdWaterBoxMinY;
// Draws all waterboxes
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)) {
return;
}

View file

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

View file

@ -74,11 +74,11 @@ u8 gAllAmmoItems[] = {
};
// Encapsulates what is drawn by the passed-in function within a border
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
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::AlignTextToFramePadding();
@ -104,14 +104,9 @@ char z2ASCII(int code) {
ret = code;
}
return char(ret);
}
typedef enum MagicLevel {
MAGIC_LEVEL_NONE,
MAGIC_LEVEL_SINGLE,
MAGIC_LEVEL_DOUBLE
};
typedef enum MagicLevel { MAGIC_LEVEL_NONE, MAGIC_LEVEL_SINGLE, MAGIC_LEVEL_DOUBLE };
std::unordered_map<int8_t, const char*> magicLevelMap = {
{ MAGIC_LEVEL_NONE, "None" },
@ -182,18 +177,22 @@ void DrawInfoTab() {
gSaveContext.health = gSaveContext.healthCapacity; // Clamp health to new max
}
int32_t health = (int32_t)gSaveContext.health;
if (SliderInt("Health", &health, intSliderOptionsBase.Tooltip("Current health. 16 units per full heart")
.Min(0).Max(gSaveContext.healthCapacity))) {
if (SliderInt("Health", &health,
intSliderOptionsBase.Tooltip("Current health. 16 units per full heart")
.Min(0)
.Max(gSaveContext.healthCapacity))) {
gSaveContext.health = (int16_t)health;
}
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.inventory.defenseHearts =
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.isDoubleMagicAcquired = gSaveContext.magicLevel == 2;
}
@ -203,7 +202,10 @@ void DrawInfoTab() {
}
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;
}
@ -239,7 +241,8 @@ void DrawInfoTab() {
Tooltip("Total number of deaths");
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);
ImGui::InputScalar("Sword Health", ImGuiDataType_U16, &gSaveContext.swordHealth);
@ -288,24 +291,24 @@ void DrawInfoTab() {
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)) {
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.");
PopStyleInput();
}
ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
static std::array<const char*, 7> minigameHS = { "Horseback Archery",
"Big Poe Points",
"Fishing",
"Malon's Obstacle Course",
"Running Man Race",
"?",
static std::array<const char*, 7> minigameHS = { "Horseback Archery", "Big Poe Points",
"Fishing", "Malon's Obstacle Course",
"Running Man Race", "?",
"Dampe's Race" };
if (ImGui::TreeNode("Minigames")) {
@ -322,7 +325,8 @@ void DrawInfoTab() {
Tooltip(fishMsg);
PopStyleInput();
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 * FishBool);
}
@ -336,32 +340,41 @@ void DrawInfoTab() {
Tooltip(fishMsg);
PopStyleInput();
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 * FishBool);
}
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 * FishBool);
}
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 * FishBool);
}
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 * FishBool);
}
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 * FishBool);
}
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 * FishBool);
}
@ -402,7 +415,9 @@ void DrawBGSItemFlag(uint8_t itemID) {
void DrawInventoryTab() {
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 x = 0; x < 6; x++) {
@ -420,7 +435,9 @@ void DrawInventoryTab() {
PushStyleButton(Colors::DarkGray);
if (item != ITEM_NONE) {
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));
if (ret) {
selectedIndex = index;
@ -437,7 +454,8 @@ void DrawInventoryTab() {
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
if (ImGui::BeginPopup(itemPopupPicker)) {
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;
ImGui::CloseCurrentPopup();
}
@ -468,7 +486,9 @@ void DrawInventoryTab() {
}
const ItemMapEntry& slotEntry = possibleItems[pickerIndex];
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));
PopStyleButton();
if (ret) {
@ -501,7 +521,8 @@ void DrawInventoryTab() {
ImGui::PushItemWidth(IMAGE_SIZE);
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);
ImGui::InputScalar("##ammoInput", ImGuiDataType_S8, &AMMO(item));
PopStyleInput();
@ -514,8 +535,8 @@ void DrawInventoryTab() {
// Trade quest flags are only used when shuffling the trade sequence, so
// don't show this if it isn't needed.
if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE)
&& ImGui::TreeNode("Adult trade quest items")) {
if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE) &&
ImGui::TreeNode("Adult trade quest items")) {
for (int i = ITEM_POCKET_EGG; i <= ITEM_CLAIM_CHECK; i++) {
DrawBGSItemFlag(i);
}
@ -560,36 +581,45 @@ void DrawFlagsTab() {
if (gPlayState != nullptr) {
Player* player = GET_PLAYER(gPlayState);
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("stateFlags1");
DrawFlagArray32("stateFlags1", player->stateFlags1, THEME_COLOR);
}, "stateFlags1");
},
"stateFlags1");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("stateFlags2");
DrawFlagArray32("stateFlags2", player->stateFlags2, THEME_COLOR);
}, "stateFlags2");
},
"stateFlags2");
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("stateFlags3");
DrawFlagArray8("stateFlags3", player->stateFlags3, THEME_COLOR);
}, "stateFlags3");
},
"stateFlags3");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("unk_6AE_rotFlags");
DrawFlagArray16("unk_6AE_rotFlags", player->unk_6AE_rotFlags, THEME_COLOR);
}, "unk_6AE_rotFlags");
},
"unk_6AE_rotFlags");
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Current Scene")) {
if (gPlayState != nullptr) {
ActorContext* act = &gPlayState->actorCtx;
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Switch");
InsertHelpHoverText("Permanently-saved switch flags");
if (Button("Set All##Switch", buttonOptionsBase.Tooltip(""))) {
@ -600,11 +630,13 @@ void DrawFlagsTab() {
act->flags.swch = 0;
}
DrawFlagArray32("Switch", act->flags.swch, THEME_COLOR);
}, "Switch");
},
"Switch");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Temp Switch");
InsertHelpHoverText("Temporary switch flags. Unset on scene transitions");
if (Button("Set All##Temp Switch", buttonOptionsBase.Tooltip(""))) {
@ -615,9 +647,11 @@ void DrawFlagsTab() {
act->flags.tempSwch = 0;
}
DrawFlagArray32("Temp Switch", act->flags.tempSwch, THEME_COLOR);
}, "Temp Switch");
},
"Temp Switch");
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Clear");
InsertHelpHoverText("Permanently-saved room-clear flags");
if (Button("Set All##Clear", buttonOptionsBase.Tooltip(""))) {
@ -628,11 +662,13 @@ void DrawFlagsTab() {
act->flags.clear = 0;
}
DrawFlagArray32("Clear", act->flags.clear, THEME_COLOR);
}, "Clear");
},
"Clear");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Temp Clear");
InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions");
if (Button("Set All##Temp Clear", buttonOptionsBase.Tooltip(""))) {
@ -643,9 +679,11 @@ void DrawFlagsTab() {
act->flags.tempClear = 0;
}
DrawFlagArray32("Temp Clear", act->flags.tempClear, THEME_COLOR);
}, "Temp Clear");
},
"Temp Clear");
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Collect");
InsertHelpHoverText("Permanently-saved collect flags");
if (Button("Set All##Collect", buttonOptionsBase.Tooltip(""))) {
@ -656,11 +694,13 @@ void DrawFlagsTab() {
act->flags.collect = 0;
}
DrawFlagArray32("Collect", act->flags.collect, THEME_COLOR);
}, "Collect");
},
"Collect");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Temp Collect");
InsertHelpHoverText("Temporary collect flags. Unset on scene transitions");
if (Button("Set All##Temp Collect", buttonOptionsBase.Tooltip(""))) {
@ -671,9 +711,11 @@ void DrawFlagsTab() {
act->flags.tempCollect = 0;
}
DrawFlagArray32("Temp Collect", act->flags.tempCollect, THEME_COLOR);
}, "Temp Collect");
},
"Temp Collect");
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Chest");
InsertHelpHoverText("Permanently-saved chest flags");
if (Button("Set All##Chest", buttonOptionsBase.Tooltip(""))) {
@ -684,34 +726,37 @@ void DrawFlagsTab() {
act->flags.chest = 0;
}
DrawFlagArray32("Chest", act->flags.chest, THEME_COLOR);
}, "Chest");
},
"Chest");
ImGui::SameLine();
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.clear = gSaveContext.sceneFlags[gPlayState->sceneNum].clear;
act->flags.collect = gSaveContext.sceneFlags[gPlayState->sceneNum].collect;
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].clear = act->flags.clear;
gSaveContext.sceneFlags[gPlayState->sceneNum].collect = act->flags.collect;
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.clear = 0;
act->flags.collect = 0;
act->flags.chest = 0;
}
ImGui::EndGroup();
} else {
ImGui::Text("Current game state does not have an active scene");
@ -745,52 +790,65 @@ void DrawFlagsTab() {
}
}
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Switch");
InsertHelpHoverText("Switch flags");
DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch, THEME_COLOR);
}, "Saved Switch");
},
"Saved Switch");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Clear");
InsertHelpHoverText("Room-clear flags");
DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear, THEME_COLOR);
}, "Saved Clear");
},
"Saved Clear");
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Collect");
InsertHelpHoverText("Collect flags");
DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect, THEME_COLOR);
}, "Saved Collect");
},
"Saved Collect");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Chest");
InsertHelpHoverText("Chest flags");
DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest, THEME_COLOR);
}, "Saved Chest");
},
"Saved Chest");
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Rooms");
InsertHelpHoverText("Flags for visted rooms");
DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms, THEME_COLOR);
}, "Saved Rooms");
},
"Saved Rooms");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Floors");
InsertHelpHoverText("Flags for visted floors");
DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors, THEME_COLOR);
}, "Saved Floors");
},
"Saved Floors");
ImGui::TreePop();
}
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
size_t selectedGsMap = 0;
ImGui::Text("Gold Skulltulas");
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
// 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;
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;
if (keepGsCountUpdated) {
for (int32_t gsFlagIndex = 0; gsFlagIndex < 6; gsFlagIndex++) {
@ -843,7 +903,8 @@ void DrawFlagsTab() {
gSaveContext.inventory.gsTokens = gsCount;
}
}
}, "Gold Skulltulas");
},
"Gold Skulltulas");
for (int i = 0; i < flagTables.size(); i++) {
const FlagTable& flagTable = flagTables[i];
@ -853,7 +914,8 @@ void DrawFlagsTab() {
if (ImGui::TreeNode(flagTable.name)) {
for (int j = 0; j < flagTable.size + 1; j++) {
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("%s", fmt::format("{:<2x}", j).c_str());
switch (flagTable.flagTableType) {
case EVENT_CHECK_INF:
@ -872,13 +934,14 @@ void DrawFlagsTab() {
DrawFlagTableArray16(flagTable, j, gSaveContext.ship.randomizerInf[j]);
break;
}
}, flagTable.name);
},
flagTable.name);
}
// make some buttons to help with fishsanity debugging
uint8_t fsMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
if (flagTable.flagTableType == RANDOMIZER_INF &&
fsMode != RO_FISHSANITY_OFF && fsMode != RO_FISHSANITY_OVERWORLD) {
if (flagTable.flagTableType == RANDOMIZER_INF && fsMode != RO_FISHSANITY_OFF &&
fsMode != RO_FISHSANITY_OVERWORLD) {
if (ImGui::Button("Catch All (Child)")) {
for (int k = RAND_INF_CHILD_FISH_1; k <= RAND_INF_CHILD_LOACH_2; 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)];
if (item != ITEM_NONE) {
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))) {
ImGui::OpenPopup(upgradePopupPicker);
}
@ -960,14 +1024,17 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const
PushStyleButton(Colors::DarkGray);
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);
ImGui::CloseCurrentPopup();
}
Tooltip("None");
} else {
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));
if (ret) {
Inventory_ChangeUpgrade(categoryId, pickerIndex);
@ -1003,7 +1070,9 @@ void DrawEquipmentTab() {
bool hasEquip = (bitMask & gSaveContext.inventory.equipment) != 0;
const ItemMapEntry& entry = itemMapping[equipmentValues[i]];
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));
if (ret) {
if (hasEquip) {
@ -1103,7 +1172,9 @@ void DrawQuestItemButton(uint32_t item) {
uint32_t bitMask = 1 << entry.id;
bool hasQuestItem = (bitMask & gSaveContext.inventory.questItems) != 0;
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));
if (ret) {
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
bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[scene]) != 0;
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));
if (ret) {
if (hasItem) {
@ -1168,7 +1241,9 @@ void DrawQuestStatusTab() {
uint32_t bitMask = 1 << entry.id;
bool hasQuestItem = (bitMask & gSaveContext.inventory.questItems) != 0;
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));
if (ret) {
if (hasQuestItem) {
@ -1211,7 +1286,8 @@ void DrawQuestStatusTab() {
InsertHelpHoverText("The number of pieces of heart acquired towards the next heart container");
PopStyleCombobox();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Dungeon Items");
static int32_t dungeonItemsScene = SCENE_DEKU_TREE;
@ -1236,19 +1312,24 @@ void DrawQuestStatusTab() {
if (dungeonItemsScene != SCENE_JABU_JABU_BOSS) {
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();
PushStyleInput(THEME_COLOR);
if (ImGui::InputScalar("##Keys", ImGuiDataType_S8, gSaveContext.inventory.dungeonKeys + dungeonItemsScene)) {
gSaveContext.ship.stats.dungeonKeys[dungeonItemsScene] = gSaveContext.inventory.dungeonKeys[dungeonItemsScene];
if (ImGui::InputScalar("##Keys", ImGuiDataType_S8,
gSaveContext.inventory.dungeonKeys + dungeonItemsScene)) {
gSaveContext.ship.stats.dungeonKeys[dungeonItemsScene] =
gSaveContext.inventory.dungeonKeys[dungeonItemsScene];
};
PopStyleInput();
} 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");
}
}, "Dungeon Items");
},
"Dungeon Items");
}
void DrawPlayerTab() {
@ -1327,16 +1408,19 @@ void DrawPlayerTab() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR);
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Link's Position");
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
ImGui::InputScalar("X##Pos", ImGuiDataType_Float, &player->actor.world.pos.x);
ImGui::InputScalar("Y##Pos", ImGuiDataType_Float, &player->actor.world.pos.y);
ImGui::InputScalar("Z##Pos", ImGuiDataType_Float, &player->actor.world.pos.z);
ImGui::PopItemWidth();
}, "Link's Position");
},
"Link's Position");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Link's Rotation");
InsertHelpHoverText("For Link's rotation in relation to the world");
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
@ -1344,9 +1428,11 @@ void DrawPlayerTab() {
ImGui::InputScalar("Y##Rot", ImGuiDataType_S16, &player->actor.world.rot.y);
ImGui::InputScalar("Z##Rot", ImGuiDataType_S16, &player->actor.world.rot.z);
ImGui::PopItemWidth();
}, "Link's Rotation");
},
"Link's Rotation");
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Link's Model Rotation");
InsertHelpHoverText("For Link's actual model");
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
@ -1354,7 +1440,8 @@ void DrawPlayerTab() {
ImGui::InputScalar("Y##ModRot", ImGuiDataType_S16, &player->actor.shape.rot.y);
ImGui::InputScalar("Z##ModRot", ImGuiDataType_S16, &player->actor.shape.rot.z);
ImGui::PopItemWidth();
}, "Link's Model Rotation");
},
"Link's Model Rotation");
ImGui::InputScalar("Linear Velocity", ImGuiDataType_Float, &player->linearVelocity);
InsertHelpHoverText("Link's speed along the XZ plane");
@ -1386,7 +1473,8 @@ void DrawPlayerTab() {
PopStyleCombobox();
ImGui::Separator();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
PushStyleCombobox(THEME_COLOR);
ImGui::Text("Link's Current Equipment");
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
@ -1413,8 +1501,7 @@ void DrawPlayerTab() {
}
player->currentSwordItemId = ITEM_SWORD_BGS;
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
}
else {
} else {
if (gSaveContext.swordHealth < 8) {
gSaveContext.swordHealth = 8;
}
@ -1430,7 +1517,6 @@ void DrawPlayerTab() {
Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_MASTER);
}
ImGui::EndCombo();
}
if (ImGui::BeginCombo("Shield", curShield)) {
if (ImGui::Selectable("None")) {
@ -1485,11 +1571,13 @@ void DrawPlayerTab() {
}
ImGui::PopItemWidth();
PopStyleCombobox();
}, "Current Equipment");
},
"Current Equipment");
ImGui::SameLine();
ImU16 one = 1;
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR);
ImGui::Text("Current Items");
@ -1499,11 +1587,13 @@ void DrawPlayerTab() {
ImGui::InputScalar("C Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[3], &one, NULL);
PopStyleInput();
ImGui::PopItemWidth();
}, "Current Items");
},
"Current Items");
if (CVarGetInteger(CVAR_ENHANCEMENT("DpadEquips"), 0)) {
ImGui::SameLine();
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
PushStyleInput(THEME_COLOR);
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 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 Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[7], &one, NULL);
ImGui::InputScalar("D-pad Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[7], &one,
NULL);
PopStyleInput();
ImGui::PopItemWidth();
}, "Current D-pad Items");
},
"Current D-pad Items");
}
ImGui::Text("Player State");
@ -1524,7 +1616,8 @@ void DrawPlayerTab() {
for (int j = 0; j <= 2; j++) {
std::string label = fmt::format("State Flags {}", j + 1);
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("%s", label.c_str());
std::vector<std::string> state = flag_strs[j];
for (int i = 0; i <= 31; i++) {
@ -1533,13 +1626,16 @@ void DrawPlayerTab() {
ImGui::Text("%s", state[i].c_str());
}
}
}, label.c_str());
},
label.c_str());
ImGui::SameLine();
}
DrawGroupWithBorder([&]() {
DrawGroupWithBorder(
[&]() {
ImGui::Text("Sword");
ImGui::Text(" %d", player->meleeWeaponState);
}, "Sword");
},
"Sword");
} else {
ImGui::Text("Global Context needed for player info!");
@ -1550,7 +1646,10 @@ void ResetBaseOptions() {
intSliderOptionsBase.Color(THEME_COLOR).Size({ 320.0f, 0.0f }).Tooltip("");
buttonOptionsBase.Color(THEME_COLOR).Size(Sizes::Inline).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() {
@ -1601,4 +1700,5 @@ void SaveEditorWindow::DrawElement() {
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
// The source was last referenced on 2022-09-03 and had a last updated value of 2020-05-02
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" },
{ 0x03, "Complained About Mido to Saria" },
{ 0x04, "Showed Mido Sword & Shield" },
@ -162,7 +165,10 @@ const std::vector<FlagTable> flagTables = {
{ 0xDD, "Obtained Skulltula House's Bombchu" },
{ 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" },
{ 0x03, "Bought Bombchu (Shelf 2: Top Right)" },
{ 0x04, "Bought Bombchu (Shelf 1: Bot. Right)" },
@ -207,7 +213,10 @@ const std::vector<FlagTable> flagTables = {
{ 0x3B, "Sold Bunny Hood" },
{ 0x3F, "Obtained Mask of Truth" },
} },
{ "Inf Flags", INF_TABLE, 0x1D, {
{ "Inf Flags",
INF_TABLE,
0x1D,
{
{ 0x00, "Greeted by Saria" },
{ 0x01, "Spoke to Saria About Obtaining Fairy" },
{ 0x03, "Complained About Mido to Saria" },
@ -331,7 +340,10 @@ const std::vector<FlagTable> flagTables = {
{ 0x1AF, "Entered Ganon's Castle (Collapsing)" },
{ 0x1D0, "No Sword on B" },
} },
{ "Event Inf Flags", EVENT_INF, 0x03, {
{ "Event Inf Flags",
EVENT_INF,
0x03,
{
{ 0x00, "Rented Horse From Ingo" },
{ 0x01, "Racing Ingo" },
{ 0x02, "Won First Race With Ingo?" },
@ -348,7 +360,10 @@ const std::vector<FlagTable> flagTables = {
{ 0x24, "Market Crowd Text Randomizer" },
{ 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_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_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_SIDE_ROOM_NEAR_DODONGOS, "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_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_SIDE_ROOM_NEAR_DODONGOS,
"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_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, "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" },
{ 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_LEFT,
"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" },
{ 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_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" },
@ -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_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_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, "SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR" },
{ RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, "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_COLOSSUS_DEKU_SCRUB_GROTTO_REAR,
"SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR" },
{ RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT,
"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_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_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_FRONT, "SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT" },
{ 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_SIDE_ROOM_NEAR_LOWER_LIZALFOS, "SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS" },
{ 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_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_FRONT,
"SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT" },
{ 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_SIDE_ROOM_NEAR_LOWER_LIZALFOS,
"SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS" },
{ 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_2, "SHOP_ITEMS_KF_SHOP_ITEM_2" },
@ -1048,10 +1083,14 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_3, "RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_3" },
{ RAND_INF_WATER_TEMPLE_MQ_LOWEST_GS_POT_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_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_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_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_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" },
@ -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_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_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_LEFT_HEART, "RAND_INF_FOREST_TEMPLE_COURTYARD_LEFT_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_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_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_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_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_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" },
@ -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_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_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_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" },
@ -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_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_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_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" },
@ -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_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_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_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_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_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_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_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_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_BASEMENT_HALLWAY_FRONT_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_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_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_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" },
@ -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_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_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_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_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_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_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_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" },
{ 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_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" },
@ -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_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_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_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_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_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" },

View file

@ -66,7 +66,8 @@ std::map<int, std::string> cmdMap = {
};
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();
@ -79,14 +80,11 @@ void PerformDisplayListSearch() {
}
// Sort the final list
std::sort(displayListSearchResults.begin(), displayListSearchResults.end(), [](const std::string& a, const std::string& b) {
return std::lexicographical_compare(
a.begin(), a.end(),
b.begin(), b.end(),
[](char c1, char c2) {
std::sort(displayListSearchResults.begin(), displayListSearchResults.end(),
[](const std::string& a, const std::string& b) {
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), [](char c1, char c2) {
return std::tolower(c1) < std::tolower(c2);
}
);
});
});
}
@ -128,7 +126,8 @@ void DLViewerWindow::DrawElement() {
}
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)) {
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);
Gfx* gfx = (Gfx*)&res->Instructions[i];
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);
@ -199,8 +199,7 @@ void DLViewerWindow::DrawElement() {
}
ImGui::PopItemWidth();
}
if (cmd == G_RDPPIPESYNC) {
}
if (cmd == G_RDPPIPESYNC) {}
if (cmd == G_SETGRAYSCALE) {
bool* state = (bool*)&gfx->words.w1;
ImGui::SameLine();
@ -304,8 +303,7 @@ void DLViewerWindow::DrawElement() {
ImGui::SameLine();
ImGui::Text("Vertex Name: %s", fileName);
}
if (cmd == G_DL) {
}
if (cmd == G_DL) {}
if (cmd == G_DL_OTR_HASH) {
gfx++;
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
if (cmd == G_SETTIMG_OTR_HASH || cmd == G_DL_OTR_HASH || cmd == G_VTX_OTR_HASH ||
cmd == G_BRANCH_Z_OTR || cmd == G_MARKER || cmd == G_MTX_OTR) {
if (cmd == G_SETTIMG_OTR_HASH || cmd == G_DL_OTR_HASH || cmd == G_VTX_OTR_HASH || cmd == G_BRANCH_Z_OTR ||
cmd == G_MARKER || cmd == G_MTX_OTR) {
i++;
ImGui::Text("%lu - Reserved - Second half of %s", i, cmdLabel.c_str());
}

View file

@ -36,4 +36,3 @@ void ResetPerformanceTimer(TimerID timer);
void ResetPerformanceTimers();
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 = {};

View file

@ -77,27 +77,35 @@ std::vector<ValueTableElement> valueTable = {
extern "C" void ValueViewer_Draw(GfxPrint* printer) {
for (int i = 0; i < valueTable.size(); i++) {
ValueTableElement& element = valueTable[i];
if (!element.isActive || !element.isPrinted || (gPlayState == NULL && element.requiresPlayState)) continue;
GfxPrint_SetColor(printer, element.color.x * 255, element.color.y * 255, element.color.z * 255, element.color.w * 255);
if (!element.isActive || !element.isPrinted || (gPlayState == NULL && element.requiresPlayState))
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);
switch (element.type) {
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;
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;
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;
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;
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;
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;
case TYPE_CHAR:
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());
break;
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;
}
}
@ -149,17 +158,16 @@ void ValueViewerWindow::DrawElement() {
ImGui::BeginGroup();
static int selectedElement = -1;
std::string selectedElementText = (selectedElement == -1) ? "Select a value" : (
std::string(valueTable[selectedElement].name) + " (" + std::string(valueTable[selectedElement].path) + ")"
);
std::string selectedElementText = (selectedElement == -1) ? "Select a value"
: (std::string(valueTable[selectedElement].name) + " (" +
std::string(valueTable[selectedElement].path) + ")");
UIWidgets::PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("##valueViewerElement", selectedElementText.c_str())) {
for (int i = 0; i < valueTable.size(); i++) {
if (valueTable[i].isActive) continue;
if (valueTable[i].isActive)
continue;
bool isSelected = (selectedElement == i);
std::string elementText = (
std::string(valueTable[i].name) + " (" + std::string(valueTable[i].path) + ")"
);
std::string elementText = (std::string(valueTable[i].name) + " (" + std::string(valueTable[i].path) + ")");
if (ImGui::Selectable(elementText.c_str(), isSelected)) {
selectedElement = i;
}
@ -181,7 +189,8 @@ void ValueViewerWindow::DrawElement() {
for (int i = 0; i < valueTable.size(); 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::PushStyleCheckbox(THEME_COLOR);
ImGui::AlignTextToFramePadding();
@ -249,7 +258,8 @@ void ValueViewerWindow::DrawElement() {
}
UIWidgets::PopStyleInput();
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();
UIWidgets::PushStyleCheckbox(THEME_COLOR);
if (ImGui::Button(("Position##" + std::string(element.name)).c_str())) {

View file

@ -42,18 +42,54 @@ const char* enemyCVarList[] = {
};
const char* enemyNameList[] = {
"Armos", "Arwing", "Baby Dodongo", "Bari",
"Beamos", "Big Skulltula", "Stalchild (Big)", "Biri",
"Iron Knuckle (Black)", "Blue Tektite", "Bubble", "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)",
"Armos",
"Arwing",
"Baby Dodongo",
"Bari",
"Beamos",
"Big Skulltula",
"Stalchild (Big)",
"Biri",
"Iron Knuckle (Black)",
"Blue Tektite",
"Bubble",
"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",
};
@ -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, 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_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping up)
// 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)
// 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)
// Doesn't work {ACTOR_EN_OKUTA, 0}, // Octorok (actor directly uses water box collision to handle hiding/popping
// up) 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) 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[] = {
@ -147,7 +184,8 @@ static int enemiesToRandomize[] = {
ACTOR_EN_FLOORMAS, // Floormaster
ACTOR_EN_RD, // Redead, Gibdo
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_KAREBABA, // Withered Deku Baba
ACTOR_EN_RR, // Like-Like
@ -171,7 +209,8 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
// This should probably be handled on OTR generation in the future when object dependency is fully removed.
// Remove bats and Skulltulas from graveyard.
// 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)) {
return 0;
}
@ -229,7 +268,8 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po
}
// 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);
int8_t timesRandomized = 1;
@ -305,7 +345,8 @@ EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
GetSelectedEnemies();
}
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);
uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE);
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.
case ACTOR_EN_WF:
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 spawning on the boat in Shadow Temple, as randomizing them places the new enemies
// down in the river.
// 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 spawning on the boat in Shadow Temple, as
// randomizing them places the new enemies down in the river.
case ACTOR_EN_TEST:
return (params != 1 && !(sceneNum == SCENE_SHADOW_TEMPLE && roomNum == 21));
// 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:
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
// most other enemies underwater with just hookshot and they're required to be killed for a grate to open.
// Don't randomize Shell Blades and Spikes in the underwater portion in Water Temple as it's impossible
// 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_NY:
return (!(!isMQ && sceneNum == SCENE_WATER_TEMPLE && roomNum == 2));
@ -403,7 +446,8 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
// Deku Tree
case SCENE_DEKU_TREE:
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
case SCENE_DODONGOS_CAVERN:
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)));
// Forest Temple
case SCENE_FOREST_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21)));
return (!(!isMQ && enemiesToExcludeClearRooms &&
(roomNum == 6 || roomNum == 10 || roomNum == 18 || roomNum == 21)) &&
!(isMQ && enemiesToExcludeClearRooms &&
(roomNum == 5 || roomNum == 6 || roomNum == 18 || roomNum == 21)));
// Fire Temple
case SCENE_FIRE_TEMPLE:
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)));
// Spirit Temple
case SCENE_SPIRIT_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 10 || roomNum == 17 || roomNum == 20)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 2 || roomNum == 4 || roomNum == 10 || roomNum == 15 || roomNum == 19 || roomNum == 20)));
return (!(!isMQ && enemiesToExcludeClearRooms &&
(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
case SCENE_SHADOW_TEMPLE:
return (!(!isMQ && enemiesToExcludeClearRooms &&
(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)));
return (
!(!isMQ && enemiesToExcludeClearRooms &&
(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
case SCENE_INSIDE_GANONS_CASTLE:
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
case SCENE_ICE_CAVERN:
return (!(!isMQ && enemiesToExcludeClearRooms && (roomNum == 1 || roomNum == 7)) &&
!(isMQ && enemiesToExcludeClearRooms && (roomNum == 3 || roomNum == 7)));
// 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:
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.
@ -452,18 +506,21 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
return (!(enemy.id == ACTOR_EN_TORCH2 && roomNum == 6) &&
!(!isMQ && enemiesToExcludeTimedRooms && (roomNum == 1 || roomNum == 7)) &&
!(!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));
// Don't allow certain enemies in Ganon's Tower because they would spawn up on the ceiling,
// becoming impossible to kill.
// Ganon's 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.
case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR:
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
// and it crashes the game. Likely because Gohma on the ceiling can't handle collision with other enemies.
// Don't allow big Stalchildren, big Peahats and the large Bari (jellyfish) during the Gohma fight because they
// 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:
return (!enemiesToExcludeTimedRooms && !(enemy.id == ACTOR_EN_SKB && enemy.params == 20) &&
!(enemy.id == ACTOR_EN_PEEHAT && enemy.params == -1));

View file

@ -18,5 +18,6 @@ extern const char* enemyNameList[];
extern void GetSelectedEnemies();
#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

View file

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

View file

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

View file

@ -54,7 +54,10 @@ bool GameInteractor::IsSaveLoaded(bool allowDbgSave) {
bool GameInteractor::IsGameplayPaused() {
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() {

View file

@ -266,7 +266,8 @@ void GameInteractor_ExecuteOnUpdateFileQuestSelection(uint8_t questIndex) {
}
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) {

View file

@ -143,11 +143,13 @@ void GameInteractor::RawAction::SetSceneFlag(int16_t sceneNum, int16_t flagType,
}
break;
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);
break;
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);
break;
case FlagType::FLAG_SCENE_COLLECTIBLE:
@ -182,11 +184,13 @@ void GameInteractor::RawAction::UnsetSceneFlag(int16_t sceneNum, int16_t flagTyp
}
break;
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);
break;
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);
break;
case FlagType::FLAG_SCENE_COLLECTIBLE:
@ -355,7 +359,8 @@ void GameInteractor::RawAction::UpdateActor(void* refActor) {
}
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->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;
@ -496,18 +501,12 @@ void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint
void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) {
const char* cvarsToLock[12] = {
CVAR_COSMETIC("Link.KokiriTunic.Locked"),
CVAR_COSMETIC("Link.GoronTunic.Locked"),
CVAR_COSMETIC("Link.ZoraTunic.Locked"),
CVAR_COSMETIC("Navi.EnemyPrimary.Locked"),
CVAR_COSMETIC("Navi.EnemySecondary.Locked"),
CVAR_COSMETIC("Navi.IdlePrimary.Locked"),
CVAR_COSMETIC("Navi.IdleSecondary.Locked"),
CVAR_COSMETIC("Navi.NPCPrimary.Locked"),
CVAR_COSMETIC("Navi.NPCSecondary.Locked"),
CVAR_COSMETIC("Navi.PropsPrimary.Locked"),
CVAR_COSMETIC("Navi.PropsSecondary.Locked"),
CVAR_COSMETIC("Link.Hair.Locked")
CVAR_COSMETIC("Link.KokiriTunic.Locked"), CVAR_COSMETIC("Link.GoronTunic.Locked"),
CVAR_COSMETIC("Link.ZoraTunic.Locked"), CVAR_COSMETIC("Navi.EnemyPrimary.Locked"),
CVAR_COSMETIC("Navi.EnemySecondary.Locked"), CVAR_COSMETIC("Navi.IdlePrimary.Locked"),
CVAR_COSMETIC("Navi.IdleSecondary.Locked"), CVAR_COSMETIC("Navi.NPCPrimary.Locked"),
CVAR_COSMETIC("Navi.NPCSecondary.Locked"), CVAR_COSMETIC("Navi.PropsPrimary.Locked"),
CVAR_COSMETIC("Navi.PropsSecondary.Locked"), CVAR_COSMETIC("Link.Hair.Locked")
};
if (excludeBiddingWarColors) {
@ -575,12 +574,14 @@ void GameInteractor::RawAction::SetPlayerInvincibility(bool active) {
/// Clears the cutscene pointer to a value safe for wrong warps.
void GameInteractor::RawAction::ClearCutscenePointer() {
if (!gPlayState) return;
if (!gPlayState)
return;
static uint32_t null_cs[] = { 0, 0 };
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()) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@ -608,8 +609,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
// 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
// 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 ||
sceneNum == SCENE_GANONDORF_BOSS || sceneNum == SCENE_FISHING_POND || sceneNum == SCENE_GANON_BOSS) {
if (sceneNum == SCENE_DODONGOS_CAVERN_BOSS || sceneNum == SCENE_WATER_TEMPLE_BOSS ||
sceneNum == SCENE_SPIRIT_TEMPLE_BOSS || sceneNum == SCENE_GANONDORF_BOSS ||
sceneNum == SCENE_FISHING_POND || sceneNum == SCENE_GANON_BOSS) {
return GameInteractionEffectQueryResult::NotPossible;
}
}
@ -649,13 +651,15 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
pos.x += 10;
pos.y += 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::Possible;
} 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;
}
}
@ -673,7 +677,8 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
if (actorId == ACTOR_EN_NIW) {
// 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);
if (cucco == NULL) {
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
@ -683,7 +688,8 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
return GameInteractionEffectQueryResult::Possible;
} else if (actorId == ACTOR_EN_BOM) {
// 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);
if (bomb == NULL) {
@ -704,5 +710,4 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t
}
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
}

View file

@ -136,7 +136,8 @@ typedef enum {
// #### `result`
// ```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`
// - None
@ -163,7 +164,8 @@ typedef enum {
// #### `result`
// ```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`
// - None
@ -302,7 +304,8 @@ typedef enum {
// #### `result`
// ```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`
// - `*EnTk`
@ -371,7 +374,8 @@ typedef enum {
// #### `result`
// ```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`
// - `*EnCow`
@ -1322,7 +1326,8 @@ typedef enum {
// Close enough & various cutscene checks
// ```c
// (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)
// ```
// #### `args`
@ -1676,7 +1681,8 @@ typedef enum {
// #### `result`
// ```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`
// - None

View file

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

View file

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

View file

@ -302,10 +302,11 @@ void LoadStatsVersion1() {
SaveManager::Instance->LoadData("fileCreatedAt", gSaveContext.ship.stats.fileCreatedAt);
SaveManager::Instance->LoadData("playTimer", gSaveContext.ship.stats.playTimer);
SaveManager::Instance->LoadData("pauseTimer", gSaveContext.ship.stats.pauseTimer);
SaveManager::Instance->LoadArray("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(
"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->LoadStruct("", [&]() {
int scene, room, sceneTime, roomTime, isRoom;
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->LoadData("", gSaveContext.ship.stats.count[i]);
});
SaveManager::Instance->LoadArray("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->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]);
});
SaveManager::Instance->LoadArray(
"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->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]); });
}
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("playTimer", saveContext->ship.stats.playTimer);
SaveManager::Instance->SaveData("pauseTimer", saveContext->ship.stats.pauseTimer);
SaveManager::Instance->SaveArray("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) {
if (saveContext->ship.stats.sceneTimestamps[i].scene != 254 && saveContext->ship.stats.sceneTimestamps[i].room != 254) {
SaveManager::Instance->SaveArray(
"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) {
if (saveContext->ship.stats.sceneTimestamps[i].scene != 254 &&
saveContext->ship.stats.sceneTimestamps[i].room != 254) {
SaveManager::Instance->SaveStruct("", [&]() {
SaveManager::Instance->SaveData("scene", saveContext->ship.stats.sceneTimestamps[i].scene);
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->SaveData("", saveContext->ship.stats.count[i]);
});
SaveManager::Instance->SaveArray("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->SaveData("", saveContext->ship.stats.entrancesDiscovered[i]);
});
SaveManager::Instance->SaveArray(
"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->SaveData("", saveContext->ship.stats.entrancesDiscovered[i]); });
}
void GameplayStatsRow(const char* label, const std::string& value, ImVec4 color = COLOR_WHITE,
@ -448,21 +451,30 @@ void DrawGameplayStatsHeader() {
GameplayStatsRow("Build Version:", (char*)gBuildVersion);
}
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 {
GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME),
gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
}
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowAdditionalTimers"), 0)) { // !Only display total game time
GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.playTimer / 2), COLOR_GREY);
GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.pauseTimer / 3), 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);
GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.playTimer / 2),
COLOR_GREY);
GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.pauseTimer / 3),
COLOR_GREY);
GameplayStatsRow("Time in scene:", formatTimestampGameplayStat(gSaveContext.ship.stats.sceneTimer / 2),
COLOR_LIGHT_BLUE);
GameplayStatsRow("Time in room:", formatTimestampGameplayStat(gSaveContext.ship.stats.roomTimer / 2),
COLOR_LIGHT_BLUE);
}
if (gPlayState != NULL && CVarGetInteger(CVAR_GAMEPLAY_STATS("ShowDebugInfo"), 0)) { // && display debug info
GameplayStatsRow("play->sceneNum:", formatHexGameplayStat(gPlayState->sceneNum), COLOR_YELLOW);
GameplayStatsRow("gSaveContext.entranceIndex:", formatHexGameplayStat(gSaveContext.entranceIndex), COLOR_YELLOW);
GameplayStatsRow("gSaveContext.cutsceneIndex:", formatHexOnlyGameplayStat(gSaveContext.cutsceneIndex), COLOR_YELLOW);
GameplayStatsRow("play->roomCtx.curRoom.num:", formatIntGameplayStat(gPlayState->roomCtx.curRoom.num), COLOR_YELLOW);
GameplayStatsRow("gSaveContext.entranceIndex:", formatHexGameplayStat(gSaveContext.entranceIndex),
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::PopStyleVar(1);
@ -484,12 +496,12 @@ void DrawGameplayStatsTimestampsTab() {
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
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::PopStyleVar(1);
}
void DrawGameplayStatsCountsTab() {
@ -520,7 +532,8 @@ void DrawGameplayStatsCountsTab() {
ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch);
GameplayStatsRow("Enemies Defeated:", formatIntGameplayStat(enemiesDefeated));
if (enemiesDefeated > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn();
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Enemy Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_ENEMIES_DEFEATED_ANUBIS; i <= COUNT_ENEMIES_DEFEATED_WOLFOS; i++) {
if (i == COUNT_ENEMIES_DEFEATED_FLOORMASTER) {
@ -537,7 +550,8 @@ void DrawGameplayStatsCountsTab() {
GameplayStatsRow("Chests Opened:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_CHESTS_OPENED]));
GameplayStatsRow("Ammo Used:", formatIntGameplayStat(ammoUsed));
if (ammoUsed > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn();
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Ammo Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_AMMO_USED_STICK; i <= COUNT_AMMO_USED_BEAN; 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("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 (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] > 0) {
GameplayStatsRow("Bunny Hood Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] / 2));
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA ||
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("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("Buttons Pressed:", formatIntGameplayStat(buttonPresses));
if (buttonPresses > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn();
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Buttons...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_BUTTON_PRESSES_A; i <= COUNT_BUTTON_PRESSES_START; i++) {
GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i]));
@ -574,16 +591,19 @@ void DrawGameplayStatsCountsTab() {
void DrawGameplayStatsBreakdownTab() {
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;
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneTimestamps[i].scene != SCENE_GROTTOS) {
if (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) &&
gSaveContext.ship.stats.sceneTimestamps[i].scene != SCENE_GROTTOS) {
name = fmt::format("{:s} Room {:d}", sceneName, gSaveContext.ship.stats.sceneTimestamps[i].room);
} else {
name = sceneName;
}
strcpy(sceneTimestampDisplay[i].name, name.c_str());
sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ?
gSaveContext.ship.stats.sceneTimestamps[i].roomTime : gSaveContext.ship.stats.sceneTimestamps[i].sceneTime;
sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0)
? gSaveContext.ship.stats.sceneTimestamps[i].roomTime
: gSaveContext.ship.stats.sceneTimestamps[i].sceneTime;
sceneTimestampDisplay[i].color = COLOR_GREY;
sceneTimestampDisplay[i].isRoom = gSaveContext.ship.stats.sceneTimestamps[i].isRoom;
}
@ -600,7 +620,9 @@ void DrawGameplayStatsBreakdownTab() {
}
std::string toPass;
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 {
toPass = ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum);
}
@ -693,7 +715,8 @@ void InitStats(bool isDebug) {
for (int scenesIdx = 0; scenesIdx < ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered); scenesIdx++) {
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;
}

View file

@ -19,17 +19,19 @@ extern "C" {
// 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
// Frame counts in z_play.c and z_kaleido_scope_call.c
#define GAMEPLAYSTAT_TOTAL_TIME (gSaveContext.ship.stats.rtaTiming ?\
(!gSaveContext.ship.stats.gameComplete ?\
(!gSaveContext.ship.stats.fileCreatedAt ? 0 : ((GetUnixTimestamp() - gSaveContext.ship.stats.fileCreatedAt) / 100)) :\
(gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \
#define GAMEPLAYSTAT_TOTAL_TIME \
(gSaveContext.ship.stats.rtaTiming \
? (!gSaveContext.ship.stats.gameComplete \
? (!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_TRIFORCE_COMPLETED])) \
:\
(gSaveContext.ship.stats.playTimer / 2 + gSaveContext.ship.stats.pauseTimer / 3))
#define CURRENT_MODE_TIMER (CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ?\
gSaveContext.ship.stats.roomTimer :\
gSaveContext.ship.stats.sceneTimer)
: (gSaveContext.ship.stats.playTimer / 2 + gSaveContext.ship.stats.pauseTimer / 3))
#define CURRENT_MODE_TIMER \
(CVarGetInteger(CVAR_GAMEPLAY_STATS("RoomBreakdown"), 0) ? gSaveContext.ship.stats.roomTimer \
: gSaveContext.ship.stats.sceneTimer)
void InitStatTracker();

View file

@ -30,10 +30,17 @@ typedef enum GetItemCategory {
} GetItemCategory;
#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) \
{ 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_CUSTOM_TABLE(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, tableId, \
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 \
{ 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)
/* 0x08 */ int16_t getItemId;
/* 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;
/* 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.
/* 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.
/* 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.
/* 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;
} GetItemEntry; // size = 0x11

View file

@ -30,16 +30,16 @@ namespace Rando {
void KaleidoEntryIcon::LoadIconTex(std::vector<Gfx>* mEntryDl) {
if (mIconFormat == G_IM_FMT_IA) {
if (mIconSize == G_IM_SIZ_8b) {
Gfx iconTexture[] = { gsDPLoadTextureBlock(mIconResourceName, G_IM_FMT_IA, G_IM_SIZ_8b, mIconWidth, mIconHeight, 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) };
Gfx iconTexture[] = { gsDPLoadTextureBlock(
mIconResourceName, G_IM_FMT_IA, G_IM_SIZ_8b, mIconWidth, mIconHeight, 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) };
mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture));
}
} else if (mIconFormat == G_IM_FMT_RGBA) {
if (mIconSize == G_IM_SIZ_32b) {
Gfx iconTexture[] = { gsDPLoadTextureBlock(mIconResourceName, G_IM_FMT_RGBA, G_IM_SIZ_32b, mIconWidth, mIconHeight, 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) };
Gfx iconTexture[] = { gsDPLoadTextureBlock(
mIconResourceName, G_IM_FMT_RGBA, G_IM_SIZ_32b, mIconWidth, mIconHeight, 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) };
mEntryDl->insert(mEntryDl->end(), std::begin(iconTexture), std::end(iconTexture));
}
}
@ -71,7 +71,8 @@ namespace Rando {
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
if (!mAchieved) {
@ -99,9 +100,9 @@ namespace Rando {
auto texture = reinterpret_cast<uintptr_t>(Ship_GetCharFontTexture(mText[i]));
auto vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(
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_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(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_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
mEntryDl->insert(mEntryDl->end(), std::begin(charTexture), std::end(charTexture));
mEntryDl->push_back(gsSP1Quadrangle(vertexStart, vertexStart + 2, vertexStart + 3, vertexStart + 1, 0));
}
@ -111,15 +112,14 @@ namespace Rando {
Kaleido::Kaleido() {
const auto ctx = Rando::Context::GetInstance();
int yOffset = 2;
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(gRupeeCounterIconTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16,
Color_RGBA8{ 0xC8, 0xFF, 0x64, 255 }, FlagType::FLAG_RANDOMIZER_INF,
static_cast<int>(RAND_INF_GREG_FOUND), 0, yOffset, "Greg"));
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
gRupeeCounterIconTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, Color_RGBA8{ 0xC8, 0xFF, 0x64, 255 },
FlagType::FLAG_RANDOMIZER_INF, static_cast<int>(RAND_INF_GREG_FOUND), 0, yOffset, "Greg"));
yOffset += 18;
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
mEntries.push_back(
std::make_shared<KaleidoEntryIconCountRequired>(
gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255,255,255,255 }, 0,
yOffset, reinterpret_cast<int*>(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected),
mEntries.push_back(std::make_shared<KaleidoEntryIconCountRequired>(
gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255, 255, 255, 255 }, 0, 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_TOTAL).Get() + 1));
yOffset += 18;
@ -130,32 +130,20 @@ namespace Rando {
}
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).IsNot(RO_BOSS_SOULS_OFF)) {
static const char* bossSoulNames[] = {
"Gohma's Soul",
"King Dodongo's Soul",
"Barinade's Soul",
"Phantom Ganon's Soul",
"Volvagia's Soul",
"Morpha's Soul",
"Bongo Bongo's Soul",
"Twinrova's Soul",
"Gohma's Soul", "King Dodongo'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++) {
mEntries.push_back(
std::make_shared<KaleidoEntryIconFlag>(
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
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;
}
}
if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON)) {
mEntries.push_back(
std::make_shared<KaleidoEntryIconFlag>(
mEntries.push_back(std::make_shared<KaleidoEntryIconFlag>(
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;
}
}
@ -211,12 +199,14 @@ namespace Rando {
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
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) {
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
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) {
@ -229,7 +219,8 @@ namespace Rando {
if (shouldScroll) {
entry->SetYOffset(yOffset);
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();
entry->Draw(play, &mEntryDl);
@ -261,9 +252,9 @@ namespace Rando {
KaleidoEntryIconFlag::KaleidoEntryIconFlag(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, FlagType flagType, int flag,
int16_t x, int16_t y, std::string name) :
mFlagType(flagType), mFlag(flag),
KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight, iconColor, x, y, std::move(name)) {
int16_t x, int16_t y, std::string name)
: mFlagType(flagType), mFlag(flag), KaleidoEntryIcon(iconResourceName, iconFormat, iconSize, iconWidth, iconHeight,
iconColor, x, y, std::move(name)) {
BuildVertices();
}
@ -271,9 +262,10 @@ namespace Rando {
mAchieved = GameInteractor::RawAction::CheckFlag(mFlagType, static_cast<int16_t>(mFlag));
}
KaleidoEntryIconCountRequired::KaleidoEntryIconCountRequired(const char *iconResourceName, int iconFormat,
int iconSize, int iconWidth, int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch,
int required, int total) : mWatch(watch), mRequired(required), mTotal(total),
KaleidoEntryIconCountRequired::KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize,
int iconWidth, int iconHeight, Color_RGBA8 iconColor,
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) {
mCount = *mWatch;
BuildText();
@ -318,9 +310,9 @@ namespace Rando {
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)
: mIconResourceName(iconResourceName), mIconFormat(iconFormat), mIconSize(iconSize),
mIconWidth(iconWidth), mIconHeight(iconHeight), mIconColor(iconColor),
KaleidoEntry(x, y, std::move(text)) {}
: mIconResourceName(iconResourceName), mIconFormat(iconFormat), mIconSize(iconSize), mIconWidth(iconWidth),
mIconHeight(iconHeight), mIconColor(iconColor), KaleidoEntry(x, y, std::move(text)) {
}
void KaleidoEntryIcon::RebuildVertices() {
free(vtx);
@ -335,11 +327,10 @@ namespace Rando {
RebuildVertices();
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") {
CalculateColors();
BuildVertices();
@ -411,7 +402,8 @@ namespace Rando {
Matrix_Translate(mX, mY, 0.0f, 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
if (!mAchieved) {
@ -426,7 +418,8 @@ namespace Rando {
// text
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
// 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 vertexStart = static_cast<int16_t>(4 * (i % 16));
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(
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_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(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_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
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(gsSPPopMatrix(G_MTX_MODELVIEW));
}
} // Rando
} // namespace Rando
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
#include <z64.h>
#ifdef __cplusplus
#include <vector>
#include <string>
@ -31,6 +30,7 @@ public:
virtual void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) = 0;
virtual void Update(PlayState* play) = 0;
void SetYOffset(int yOffset);
protected:
int16_t mX;
int16_t mY;
@ -39,7 +39,6 @@ protected:
Vtx* vtx;
std::string mText;
bool mAchieved = false;
};
/**
@ -63,6 +62,7 @@ public:
Color_RGBA8 iconColor, int16_t x, int16_t y, std::string text = "");
void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override;
void RebuildVertices();
protected:
const char* mIconResourceName;
int mIconFormat;
@ -98,6 +98,7 @@ public :
Color_RGBA8 iconColor, FlagType flagType, int flag, int16_t x, int16_t y,
std::string name = "");
void Update(PlayState* play) override;
private:
FlagType mFlagType;
int mFlag;
@ -126,9 +127,11 @@ public:
* @param required The amount of this collectible required to beat the seed. Set to 0 to not render.
* @param 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,
Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch, int required = 0, int total = 0);
KaleidoEntryIconCountRequired(const char* iconResourceName, int iconFormat, int iconSize, int iconWidth,
int iconHeight, Color_RGBA8 iconColor, int16_t x, int16_t y, int* watch,
int required = 0, int total = 0);
void Update(PlayState* play) override;
private:
int* mWatch;
int mRequired;
@ -143,6 +146,7 @@ public:
KaleidoEntryOcarinaButtons(int16_t x, int16_t y);
void Update(PlayState* play) override;
void Draw(PlayState* play, std::vector<Gfx>* mEntryDl) override;
private:
void CalculateColors();
@ -155,13 +159,14 @@ public:
Kaleido();
void Draw(PlayState* play);
void Update(PlayState* play);
private:
std::vector<std::shared_ptr<KaleidoEntry>> mEntries;
std::vector<Gfx> mEntryDl;
int mTopIndex = 0;
int mNumVisible = 7;
};
} // Rando
} // namespace Rando
extern "C" {
#endif
@ -172,5 +177,4 @@ void RandoKaleido_UpdateMiscCollectibles(int16_t inDungeonScene);
#endif
void RandoKaleido_RegisterHooks();
#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.
void SwitchAge() {
if (gPlayState == NULL) return;
if (gPlayState == NULL)
return;
Player* player = GET_PLAYER(gPlayState);
@ -114,14 +115,16 @@ void RegisterOcarinaTimeTravel() {
}
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* 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* 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);
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 doesntNeedOcarinaOfTime = CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2;
bool hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER);
@ -191,13 +194,14 @@ void RegisterShadowTag() {
static bool hasAffectedHealth = false;
void UpdatePermanentHeartLossState() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!GameInteractor::IsSaveLoaded())
return;
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) {
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 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);
gSaveContext.healthCapacity = MAX(newCapacity, gSaveContext.healthCapacity);
@ -213,7 +217,8 @@ void RegisterPermanentHeartLoss() {
});
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) {
gSaveContext.healthCapacity -= 16;
@ -225,12 +230,16 @@ void RegisterPermanentHeartLoss() {
void RegisterDeleteFileOnDeath() {
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) {
SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum);
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
{ SCENE_ZORAS_FOUNTAIN, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } },
// 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 } } },
// Kak
{ SCENE_KAKARIKO_VILLAGE, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } },
@ -293,7 +305,8 @@ void RegisterDaytimeGoldSkultullas() {
bool IsHyperBossesActive() {
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() {
@ -304,21 +317,22 @@ void UpdateHyperBossesState() {
}
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.
Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor);
uint8_t isBossActor =
actor->id == ACTOR_BOSS_GOMA || // Gohma
uint8_t isBossActor = actor->id == ACTOR_BOSS_GOMA || // Gohma
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath
actor->id == ACTOR_BOSS_VA || // Barinade
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder
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_BOSS_MO || // Morpha
actor->id == ACTOR_BOSS_SST || // Bongo Bongo
@ -348,9 +362,8 @@ void UpdateHyperBossesState() {
void RegisterHyperBosses() {
UpdateHyperBossesState();
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int16_t fileNum) {
UpdateHyperBossesState();
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>(
[](int16_t fileNum) { UpdateHyperBossesState(); });
}
void UpdateHyperEnemiesState() {
@ -361,7 +374,8 @@ void UpdateHyperEnemiesState() {
}
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.
Player* player = GET_PLAYER(gPlayState);
@ -428,7 +442,8 @@ void UpdateDirtPathFixState(int32_t sceneNum) {
case SCENE_HYRULE_FIELD:
case SCENE_KOKIRI_FOREST:
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;
default:
CVarClear(CVAR_Z_FIGHTING_MODE);
@ -436,9 +451,8 @@ void UpdateDirtPathFixState(int32_t sceneNum) {
}
void RegisterMenuPathFix() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>([](int32_t sceneNum) {
UpdateDirtPathFixState(sceneNum);
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(
[](int32_t sceneNum) { UpdateDirtPathFixState(sceneNum); });
}
void UpdateMirrorModeState(int32_t sceneNum) {
@ -446,27 +460,28 @@ void UpdateMirrorModeState(int32_t sceneNum) {
bool nextMirroredWorld = false;
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_GANON_BOSS);
if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) {
uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
: gSaveContext.ship.stats.fileCreatedAt);
uint32_t seed =
sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(seed);
}
bool randomMirror = Random(0, 2) == 1;
if (
mirroredMode == MIRRORED_WORLD_ALWAYS ||
if (mirroredMode == MIRRORED_WORLD_ALWAYS ||
((mirroredMode == MIRRORED_WORLD_RANDOM || mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED) && randomMirror) ||
// 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_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;
CVarSetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 1);
} else {
@ -481,25 +496,33 @@ void UpdateMirrorModeState(int32_t sceneNum) {
}
void RegisterMirrorModeHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) {
UpdateMirrorModeState(sceneNum);
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(
[](int32_t sceneNum) { UpdateMirrorModeState(sceneNum); });
}
void UpdatePatchHand() {
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(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2", 85, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1", 51, gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot1", 84,
gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingHookshotNearDL, "childHookshot2", 85,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow1", 51,
gsSPDisplayListOTRFilePath(gLinkChildRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultRightHandHoldingBowNearDL, "childBow2", 52, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1", 104, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2", 105, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1", 79, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword1", 104,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingMasterSwordNearDL, "childMasterSword2", 105,
gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword1", 79,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultLeftHandHoldingBgsNearDL, "childBiggoronSword2", 80, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1", 76, gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2", 77, gsSPEndDisplayList());
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife1", 76,
gsSPDisplayListOTRFilePath(gLinkChildLeftFistNearDL));
ResourceMgr_PatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2", 77,
gsSPEndDisplayList());
} else {
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "childHammer1");
@ -516,10 +539,14 @@ void UpdatePatchHand() {
ResourceMgr_UnpatchGfxByName(gLinkAdultHandHoldingBrokenGiantsKnifeDL, "childBrokenGiantsKnife2");
}
if ((CVarGetInteger(CVAR_ENHANCEMENT("EquipmentAlwaysVisible"), 0)) && LINK_IS_ADULT) {
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50, gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield", 49, gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword", 13,
gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot", 13,
gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildLeftFistAndBoomerangNearDL, "adultBoomerang", 50,
gsSPDisplayListOTRFilePath(gLinkAdultLeftHandClosedNearDL));
ResourceMgr_PatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield", 49,
gsSPDisplayListOTRFilePath(gLinkAdultRightHandClosedNearDL));
} else {
ResourceMgr_UnpatchGfxByName(gLinkChildLeftFistAndKokiriSwordNearDL, "adultKokiriSword");
ResourceMgr_UnpatchGfxByName(gLinkChildRightHandHoldingSlingshotNearDL, "adultSlingshot");
@ -527,7 +554,8 @@ void UpdatePatchHand() {
ResourceMgr_UnpatchGfxByName(gLinkChildRightFistAndDekuShieldNearDL, "adultDekuShield");
}
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());
} else {
ResourceMgr_UnpatchGfxByName(gLinkAdultLeftHandHoldingHammerNearDL, "hammerHand1");
@ -536,9 +564,8 @@ void UpdatePatchHand() {
}
void RegisterPatchHandHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int32_t sceneNum) {
UpdatePatchHand();
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(
[](int32_t sceneNum) { UpdatePatchHand(); });
}
void RegisterResetNaviTimer() {
@ -655,16 +682,14 @@ void RegisterEnemyDefeatCounts() {
}
break;
case ACTOR_EN_REEBA:
{
case ACTOR_EN_REEBA: {
EnReeba* reeba = (EnReeba*)actor;
if (reeba->isBig) {
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++;
} else {
gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
}
}
break;
} break;
case ACTOR_EN_MB:
if (actor->params == 0) {
@ -798,9 +823,8 @@ void UpdateHurtContainerModeState(bool newState) {
}
void RegisterHurtContainerModeHandler() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) {
UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0));
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>(
[](int32_t fileNum) { UpdateHurtContainerModeState(CVarGetInteger(CVAR_ENHANCEMENT("HurtContainer"), 0)); });
}
void RegisterRandomizedEnemySizes() {
@ -820,7 +844,8 @@ void RegisterRandomizedEnemySizes() {
actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH;
// 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;
}
@ -860,7 +885,8 @@ void RegisterOpenAllHours() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* 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) {
case 4753: // Night Market Bazaar
case 1678: // Night Potion Shop
@ -892,47 +918,65 @@ void PatchToTMedallions() {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_StartGrayscale", 7, gsSPGrayscale(true));
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 {
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)) {
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 {
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)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69, gsDPSetGrayscaleColor(255, 255, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16, gsDPSetGrayscaleColor(255, 255, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69,
gsDPSetGrayscaleColor(255, 255, 0, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16,
gsDPSetGrayscaleColor(255, 255, 0, 255));
} else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69, gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16, gsDPSetGrayscaleColor(255, 255, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69,
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)) {
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 {
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)) {
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 {
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)) {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142, gsDPSetGrayscaleColor(212, 0, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27, gsDPSetGrayscaleColor(212, 0, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142,
gsDPSetGrayscaleColor(212, 0, 255, 255));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27,
gsDPSetGrayscaleColor(212, 0, 255, 255));
} else {
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142, 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_MakePurple", 142,
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_007FD0, "ToTMedallions_2_EndGrayscaleAndEndDlist", 51, gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_EndGrayscaleAndEndDlist", 160,
gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_EndGrayscaleAndEndDlist", 51,
gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
} else {
// Unpatch everything
ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_StartGrayscale");
@ -953,7 +997,8 @@ void PatchToTMedallions() {
void RegisterToTMedallions() {
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;
}
PatchToTMedallions();
@ -966,7 +1011,6 @@ void RegisterToTMedallions() {
});
}
void RegisterFloorSwitchesHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
Actor* actor = static_cast<Actor*>(refActor);
@ -991,10 +1035,10 @@ void RegisterPauseMenuHooks() {
return;
}
if (!pauseWarpHooksRegistered) {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoUpdate>([]() {PauseWarp_HandleSelection();});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
PauseWarp_Execute();
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoUpdate>(
[]() { PauseWarp_HandleSelection(); });
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(
[]() { PauseWarp_Execute(); });
pauseWarpHooksRegistered = true;
}
});
@ -1004,7 +1048,6 @@ void RegisterCustomSkeletons() {
static int8_t previousTunic = -1;
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded() || gPlayState == NULL) {
return;
}

View file

@ -130,9 +130,9 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
int16_t vertexStart = 4 * (i % 16);
// Multi-instruction macro, need to insert all to the dl buffer
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(
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_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
Gfx charTexture[] = { gsDPLoadTextureBlock_4b(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_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD) };
nameTagDl.insert(nameTagDl.end(), std::begin(charTexture), std::end(charTexture));
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));
// 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,
// 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');
}), processedText.end());
}),
processedText.end());
int16_t numChar = processedText.length();
int16_t numLines = 1;

View file

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

View file

@ -5,40 +5,76 @@
namespace CustomMessages {
using namespace std::literals::string_literals;
std::string MESSAGE_END() { return "\x7F\x00"s; }
std::string WAIT_FOR_INPUT() { return "\x7F\x01"s; }
std::string MESSAGE_END() {
return "\x7F\x00"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 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 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 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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -15,12 +15,8 @@
using namespace Rando;
HintDistributionSetting::HintDistributionSetting(std::string _name,
HintType _type,
uint32_t _weight,
uint8_t _fixed,
uint8_t _copies,
std::function<bool(RandomizerCheck)> _filter,
HintDistributionSetting::HintDistributionSetting(std::string _name, HintType _type, uint32_t _weight, uint8_t _fixed,
uint8_t _copies, std::function<bool(RandomizerCheck)> _filter,
uint8_t _dungeonLimit) {
name = _name;
type = _type;
@ -32,8 +28,10 @@ HintDistributionSetting::HintDistributionSetting(std::string _name,
}
//RANDOTODO rearrange once all HintText's have names
HintText::HintText(CustomMessage clearText_, std::vector<CustomMessage> ambiguousText_, std::vector<CustomMessage> obscureText_, CustomMessage name_)
: clearText(std::move(clearText_)), ambiguousText(std::move(ambiguousText_)), obscureText(std::move(obscureText_)), name(std::move(name_)){}
HintText::HintText(CustomMessage clearText_, std::vector<CustomMessage> ambiguousText_,
std::vector<CustomMessage> obscureText_, CustomMessage name_)
: clearText(std::move(clearText_)), ambiguousText(std::move(ambiguousText_)), obscureText(std::move(obscureText_)), name(std::move(name_)) {
}
const CustomMessage& HintText::GetClear() const {
return clearText;
@ -100,20 +98,20 @@ const CustomMessage HintText::GetMessageCopy() const {
}
bool HintText::operator==(const HintText& right) const {
return obscureText == right.obscureText &&
ambiguousText == right.ambiguousText &&
clearText == right.clearText;
return obscureText == right.obscureText && ambiguousText == right.ambiguousText && clearText == right.clearText;
}
bool HintText::operator!=(const HintText& right) const {
return !operator==(right);
}
StaticHintInfo::StaticHintInfo(HintType _type, std::vector<RandomizerHintTextKey> _hintKeys, RandomizerSettingKey _setting,
std::variant<bool, uint8_t> _condition, std::vector<RandomizerCheck> _targetChecks,
std::vector<RandomizerGet> _targetItems, std::vector<RandomizerCheck> _hintChecks, bool _yourPocket, int _num):
type(_type), hintKeys(_hintKeys), setting(_setting), condition(_condition), targetChecks(_targetChecks),
targetItems(_targetItems), hintChecks(_hintChecks), yourPocket(_yourPocket), num(_num){}
StaticHintInfo::StaticHintInfo(HintType _type, std::vector<RandomizerHintTextKey> _hintKeys,
RandomizerSettingKey _setting, std::variant<bool, uint8_t> _condition,
std::vector<RandomizerCheck> _targetChecks, std::vector<RandomizerGet> _targetItems,
std::vector<RandomizerCheck> _hintChecks, bool _yourPocket, int _num)
: type(_type), hintKeys(_hintKeys), setting(_setting), condition(_condition), targetChecks(_targetChecks),
targetItems(_targetItems), hintChecks(_hintChecks), yourPocket(_yourPocket), num(_num) {
}
RandomizerHintTextKey GetRandomJunkHint() {
// Temp code to handle random junk hints now I work in keys instead of a vector of HintText
@ -127,7 +125,6 @@ RandomizerHintTextKey GetRandomGanonJoke(){
return (RandomizerHintTextKey)(Random(0, range) + RHT_GANON_JOKE01);
}
bool FilterWotHLocations(RandomizerCheck loc) {
auto ctx = Rando::Context::GetInstance();
return ctx->GetItemLocation(loc)->IsWothCandidate();
@ -229,7 +226,8 @@ uint8_t StonesRequiredBySettings() {
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get();
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
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;
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
@ -249,14 +247,16 @@ uint8_t MedallionsRequiredBySettings() {
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get();
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
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;
}
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() });
} 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) });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) &&
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 3) });
}
return medallions;
@ -275,45 +275,55 @@ uint8_t TokensRequiredBySettings() {
}
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();
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
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() {
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH,
[]() {
auto ctx = Rando::Context::GetInstance();
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();
return StonesRequiredBySettings() < 2 && !ctx->GetOption(RSK_OOT_HINT);
}),
std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }),
std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }),
std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, []() {
std::make_pair(RC_DMT_TRADE_CLAIM_CHECK,
[]() {
auto ctx = Rando::Context::GetInstance();
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();
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();
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();
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();
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();
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();
return !ctx->GetOption(RSK_KAK_100_SKULLS_HINT) && TokensRequiredBySettings() < 100;
}),
@ -339,7 +349,8 @@ static std::vector<RandomizerCheck> GetAccessibleGossipStones(const RandomizerCh
return accessibleGossipStones;
}
bool IsReachableWithout(std::vector<RandomizerCheck> locsToCheck, RandomizerCheck excludedCheck, bool resetAfter = true){
bool IsReachableWithout(std::vector<RandomizerCheck> locsToCheck, RandomizerCheck excludedCheck,
bool resetAfter = true) {
// temporarily remove the hinted location's item, and then perform a
// reachability search for this check RANDOTODO convert excludedCheck to an ItemLocation
auto ctx = Rando::Context::GetInstance();
@ -368,21 +379,19 @@ static void SetAllInAreaAsHintAccesible(RandomizerArea area, std::vector<Randomi
}
}
static void AddGossipStoneHint( const RandomizerCheck gossipStone,
const HintType hintType,
const std::string distributionName,
const std::vector<RandomizerHintTextKey> hintKeys,
const std::vector<RandomizerCheck> locations,
const std::vector<RandomizerArea> areas,
static void AddGossipStoneHint(const RandomizerCheck gossipStone, const HintType hintType,
const std::string distributionName, const std::vector<RandomizerHintTextKey> hintKeys,
const std::vector<RandomizerCheck> locations, const std::vector<RandomizerArea> areas,
const std::vector<TrialKey> trials) {
auto ctx = Rando::Context::GetInstance();
ctx->AddHint(StaticData::gossipStoneCheckToHint[gossipStone], 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
ctx->AddHint(StaticData::gossipStoneCheckToHint[gossipStone],
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,
const HintType hintType,
const std::string distributionName,
static void AddGossipStoneHintCopies(uint8_t copies, const HintType hintType, const std::string distributionName,
const std::vector<RandomizerHintTextKey> hintKeys = {},
const std::vector<RandomizerCheck> locations = {},
const std::vector<RandomizerArea> areas = {},
@ -427,11 +436,8 @@ static bool CreateHint(RandomizerCheck location, uint8_t copies, HintType type,
return true;
}
static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHintLocations,
uint8_t copies,
HintType type,
std::string distributionName) {
static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHintLocations, uint8_t copies,
HintType type, std::string distributionName) {
auto ctx = Rando::Context::GetInstance();
// return if there aren't any hintable locations or gossip stones available
@ -447,7 +453,8 @@ static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHi
SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n");
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(Rando::StaticData::GetLocation(hintedLocation)->GetName());
@ -466,8 +473,8 @@ static std::vector<RandomizerCheck> FilterHintability(std::vector<RandomizerChec
std::function<bool(RandomizerCheck)> extraFilter = NoFilter) {
auto ctx = Rando::Context::GetInstance();
return FilterFromPool(locations, [extraFilter, ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsAHintAccessible())
&& extraFilter(loc);
return ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsAHintAccessible()) &&
extraFilter(loc);
});
}
@ -486,7 +493,8 @@ static void CreateTrialHints(uint8_t copies) {
} else if (ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) { // zero trials
AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", { RHT_ZERO_TRIALS });
} else {
std::vector<TrialInfo*> trials = ctx->GetTrials()->GetTrialList(); //there's probably a way to remove this assignment
std::vector<TrialInfo*> trials =
ctx->GetTrials()->GetTrialList(); // there's probably a way to remove this assignment
if (ctx->GetOption(RSK_TRIAL_COUNT).Get() >= 4) { // 4 or 5 required trials, get skipped trials
trials = FilterFromPool(trials, [](TrialInfo* trial) { return trial->IsSkipped(); });
} else { // 1 to 3 trials, get requried trials
@ -508,22 +516,28 @@ void CreateWarpSongTexts() {
RandomizerArea destination = entrance->GetConnectedRegion()->GetFirstArea();
switch (entrance->GetIndex()) {
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;
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;
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;
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;
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;
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;
default:
break;
@ -539,35 +553,49 @@ int32_t getRandomWeight(int32_t totalWeight){
return Random(1, totalWeight);
}
static void DistributeHints(std::vector<uint8_t>& selected, size_t stoneCount, std::vector<HintDistributionSetting> distTable, uint8_t junkWieght, bool addFixed = true){
static void DistributeHints(std::vector<uint8_t>& selected, size_t stoneCount,
std::vector<HintDistributionSetting> distTable, uint8_t junkWieght, bool addFixed = true) {
int32_t totalWeight = junkWieght; // Start with our Junk Weight, the natural chance of a junk hint
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
totalWeight += distTable[c].weight; //Note that PlaceHints will set weights of distributions to zero if it can't place anything from them
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
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;
stoneCount -= distTable[c].fixed * distTable[c].copies;
}
}
int32_t currentWeight = getRandomWeight(totalWeight); //Initialise with the first random weight from 1 to the total.
while(stoneCount > 0 && totalWeight > 0){//Loop until we run out of stones or have no TotalWeight. 0 totalWeight means junkWeight is 0
int32_t currentWeight = getRandomWeight(totalWeight); // Initialise with the first random weight from 1 to the
// total.
while (stoneCount > 0 &&
totalWeight >
0) { // Loop until we run out of stones or have no TotalWeight. 0 totalWeight means junkWeight is 0
// and that all weights have been 0'd out for another reason, and skips to placing all junk hints
for (size_t distribution = 0; distribution < distTable.size(); distribution++) {
currentWeight -= distTable[distribution].weight; //go over each distribution, subtracting the weight each time. Once we reach zero or less,
currentWeight -=
distTable[distribution]
.weight; // go over each distribution, subtracting the weight each time. Once we reach zero or less,
if (currentWeight <= 0) { // tell the system to make 1 of that hint, unless not enough stones remain
if (stoneCount >= distTable[distribution].copies && distTable[distribution].copies > 0) {
selected[distribution] += 1; //if we have enough stones, and copies are not zero, assign 1 to this hint type, remove the stones, and break
selected[distribution] += 1; // if we have enough stones, and copies are not zero, assign 1 to this
// hint type, remove the stones, and break
stoneCount -= distTable[distribution].copies;
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
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
} 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
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;
}
}
}
// if there's still weight then it's junk, as the leftover weight is junkWeight
if (currentWeight > 0){ //zero TotalWeight breaks the while loop and hits the fallback, so skipping this is fine in that case
if (currentWeight >
0) { // zero TotalWeight breaks the while loop and hits the fallback, so skipping this is fine in that case
selected[selected.size() - 1] += 1;
stoneCount -= 1;
}
@ -586,14 +614,17 @@ uint8_t PlaceHints(std::vector<uint8_t>& selectedHints, std::vector<HintDistribu
std::vector<RandomizerCheck> hintTypePool = FilterHintability(ctx->allLocations, distribution.filter);
for (uint8_t numHint = 0; numHint < selectedHints[curSlot]; numHint++) {
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;
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;
selectedHints[curSlot] = 0; //as distTable is passed by refernce here, these changes stick for the rest of this seed generation
selectedHints[curSlot] = 0; // as distTable is passed by refernce here, these changes stick for the rest
// of this seed generation
distTable[curSlot].copies = 0; // and prevent future distribution from choosing this slot
distTable[curSlot].weight = 0;
return hintsToRemove;
@ -630,8 +661,7 @@ void CreateStoneHints() {
// If we have Rainbow Bridge set to Greg and the greg hint isn't useful, add a hint for where Greg is
// Do we really need this with the greg hint?
auto gregLocations = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return (
(ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) &&
return ((ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) &&
ctx->GetItemLocation(loc)->IsHintable() &&
!(ctx->GetOption(RSK_GREG_HINT) && (IsReachableWithout({ RC_GREG_HINT }, loc, true)));
});
@ -678,16 +708,20 @@ void CreateStoneHints() {
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 = {};
auto ctx = Rando::Context::GetInstance();
for (size_t c = 0; c < items.size(); c++) {
std::vector<RandomizerCheck> found = FilterFromPool(ctx->allLocations, [items, ctx, c](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == items[c];});
std::vector<RandomizerCheck> found =
FilterFromPool(ctx->allLocations, [items, ctx, c](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == items[c];
});
if (found.size() > 0) {
locations.push_back(found[0]);
// 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();
}
} else {
@ -702,10 +736,12 @@ void CreateChildAltarHint() {
if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled() && ctx->GetOption(RSK_TOT_ALTAR_HINT)) {
std::vector<RandomizerCheck> stoneLocs = {};
// force marking the rewards as hinted if they are at the end of dungeons as they can be inferred
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) {
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) ||
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) {
stoneLocs = FindItemsAndMarkHinted({ RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE }, {});
} 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 = {};
for (auto loc : stoneLocs) {
@ -723,11 +759,14 @@ void CreateAdultAltarHint() {
std::vector<RandomizerCheck> medallionLocs = {};
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
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)) {
medallionLocs = FindItemsAndMarkHinted({RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION},
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)) {
medallionLocs = FindItemsAndMarkHinted({ RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION,
RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION },
{});
} else {
medallionLocs = FindItemsAndMarkHinted({RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION},
medallionLocs = FindItemsAndMarkHinted({ RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION,
RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION },
{ RC_ALTAR_HINT_ADULT });
}
}
@ -746,7 +785,8 @@ void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){
if (!ctx->GetHint(hint)->IsEnabled()) {
OptionValue& option = ctx->GetOption(staticData.setting);
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 = {};
if (staticData.targetItems.size() > 0) {
@ -760,7 +800,8 @@ void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){
for (auto loc : locations) {
ctx->GetItemLocation(loc)->SetHintAccesible();
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(Rando::StaticData::GetLocation(loc)->GetName());
// assert(false);
@ -770,13 +811,15 @@ void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){
}
}
// hintKeys are defaulted to in the hint object and do not need to be specified
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,
std::vector<RandomizerGet> items, std::vector<RandomizerCheck> hintChecks, bool yourPocket = false) {
std::vector<RandomizerGet> items, std::vector<RandomizerCheck> hintChecks,
bool yourPocket = false) {
// RANDOTODO choose area in case there are multiple
auto ctx = Rando::Context::GetInstance();
std::vector<RandomizerCheck> locations = FindItemsAndMarkHinted(items, hintChecks);
@ -798,10 +841,13 @@ void CreateGanondorfHint(){
auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_GANONDORF_HINT) && !ctx->GetHint(RH_GANONDORF_HINT)->IsEnabled()) {
if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) {
CreateStaticItemHint(RH_GANONDORF_HINT, {RHT_GANONDORF_HINT_LA_ONLY, RHT_GANONDORF_HINT_MS_ONLY, RHT_GANONDORF_HINT_LA_AND_MS},
CreateStaticItemHint(
RH_GANONDORF_HINT,
{ RHT_GANONDORF_HINT_LA_ONLY, RHT_GANONDORF_HINT_MS_ONLY, RHT_GANONDORF_HINT_LA_AND_MS },
{ RG_LIGHT_ARROWS, RG_MASTER_SWORD }, { RC_GANONDORF_HINT }, true);
} else {
CreateStaticItemHint(RH_GANONDORF_HINT, {RHT_GANONDORF_HINT_LA_ONLY}, {RG_LIGHT_ARROWS}, {RC_GANONDORF_HINT}, true);
CreateStaticItemHint(RH_GANONDORF_HINT, { RHT_GANONDORF_HINT_LA_ONLY }, { RG_LIGHT_ARROWS },
{ RC_GANONDORF_HINT }, true);
}
}
}

View file

@ -13,33 +13,13 @@
std::vector<RandomizerGet> ItemPool = {};
std::vector<RandomizerGet> PendingJunkPool = {};
const std::array<RandomizerGet, 9> dungeonRewards = {
RG_KOKIRI_EMERALD,
RG_GORON_RUBY,
RG_ZORA_SAPPHIRE,
RG_FOREST_MEDALLION,
RG_FIRE_MEDALLION,
RG_WATER_MEDALLION,
RG_SPIRIT_MEDALLION,
RG_SHADOW_MEDALLION,
RG_LIGHT_MEDALLION,
RG_KOKIRI_EMERALD, RG_GORON_RUBY, 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 = {
RG_BOMBS_5,
RG_BOMBS_10,
RG_BOMBS_20,
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,
RG_BOMBS_5, RG_BOMBS_10, RG_BOMBS_20, 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 = {
RG_BIGGORON_SWORD,
@ -212,13 +192,7 @@ const std::array<RandomizerGet, 2> DC_MQ = {
RG_BLUE_RUPEE,
};
const std::array<RandomizerGet, 7> JB_MQ = {
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_DEKU_NUTS_5, RG_RECOVERY_HEART, RG_DEKU_SHIELD, RG_DEKU_STICK_1,
};
const std::array<RandomizerGet, 3> FoT_Vanilla = {
RG_RECOVERY_HEART,
@ -255,13 +229,7 @@ const std::array<RandomizerGet, 3> ShT_MQ = {
RG_RED_RUPEE,
};
const std::array<RandomizerGet, 7> BW_Vanilla = {
RG_RECOVERY_HEART,
RG_BOMBS_10,
RG_HUGE_RUPEE,
RG_DEKU_NUTS_5,
RG_DEKU_NUTS_10,
RG_DEKU_SHIELD,
RG_HYLIAN_SHIELD,
RG_RECOVERY_HEART, 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 = {
RG_ARROWS_30,
@ -270,11 +238,7 @@ const std::array<RandomizerGet, 4> GTG_Vanilla = {
RG_HUGE_RUPEE,
};
const std::array<RandomizerGet, 5> GTG_MQ = {
RG_LOSER_GREEN_RUPEE,
RG_LOSER_GREEN_RUPEE,
RG_ARROWS_10,
RG_GREEN_RUPEE,
RG_PURPLE_RUPEE,
RG_LOSER_GREEN_RUPEE, RG_LOSER_GREEN_RUPEE, RG_ARROWS_10, RG_GREEN_RUPEE, RG_PURPLE_RUPEE,
};
const std::array<RandomizerGet, 4> GC_Vanilla = {
RG_BLUE_RUPEE,
@ -283,11 +247,7 @@ const std::array<RandomizerGet, 4> GC_Vanilla = {
RG_ARROWS_30,
};
const std::array<RandomizerGet, 5> GC_MQ = {
RG_ARROWS_10,
RG_ARROWS_10,
RG_BOMBS_5,
RG_RED_RUPEE,
RG_RECOVERY_HEART,
RG_ARROWS_10, RG_ARROWS_10, RG_BOMBS_5, RG_RED_RUPEE, RG_RECOVERY_HEART,
};
const std::array<RandomizerGet, 11> normalBottles = {
RG_EMPTY_BOTTLE,
@ -303,99 +263,29 @@ const std::array<RandomizerGet, 11> normalBottles = {
RG_BOTTLE_WITH_BLUE_FIRE,
};
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_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,
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_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 = {
RG_BLUE_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_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,
RG_BLUE_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_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 = {
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_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,
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_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 = {
RG_ZELDAS_LULLABY,
RG_EPONAS_SONG,
RG_SUNS_SONG,
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,
RG_ZELDAS_LULLABY, RG_EPONAS_SONG, RG_SUNS_SONG, 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 = {
RG_POCKET_EGG,
@ -414,8 +304,7 @@ void AddItemToPool(std::vector<RandomizerGet>& pool, RandomizerGet item, size_t
pool.insert(pool.end(), count, item);
}
template <typename FromPool>
static void AddItemsToPool(std::vector<RandomizerGet>& toPool, const FromPool& fromPool) {
template <typename FromPool> static void AddItemsToPool(std::vector<RandomizerGet>& toPool, const FromPool& fromPool) {
AddElementsToPool(toPool, fromPool);
}
@ -429,7 +318,8 @@ static void AddRandomBottle(std::vector<RandomizerGet>& bottlePool) {
RandomizerGet GetJunkItem() {
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;
} else if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_EXTRA)) {
return RandomElement(JunkPoolItems);
@ -853,7 +743,8 @@ void GenerateItemPool() {
}
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);
}
AddItemToMainPool(RG_HUGE_RUPEE);
@ -943,7 +834,8 @@ void GenerateItemPool() {
}
}
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
if (ctx->GetOption(RSK_KEYRINGS_GERUDO_FORTRESS) && ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) && ctx->GetOption(RSK_KEYRINGS) ) {
if (ctx->GetOption(RSK_KEYRINGS_GERUDO_FORTRESS) &&
ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) && ctx->GetOption(RSK_KEYRINGS)) {
AddItemToPool(PendingJunkPool, RG_HIDEOUT_KEY_RING);
} else {
AddItemToPool(PendingJunkPool, RG_HIDEOUT_SMALL_KEY);
@ -964,7 +856,8 @@ void GenerateItemPool() {
}
// 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);
ctx->possibleIceTrapModels.push_back(RG_GERUDO_MEMBERSHIP_CARD);
} else if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
@ -999,7 +892,9 @@ void GenerateItemPool() {
}
// 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()) {
AddItemToPool(PendingJunkPool, RG_BOTW_KEY_RING);
} 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_FIRE_TEMPLE_BOSS_KEY);
AddItemToPool(PendingJunkPool, RG_WATER_TEMPLE_BOSS_KEY);
@ -1050,7 +947,9 @@ void GenerateItemPool() {
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);
}
}
@ -1083,13 +982,9 @@ void GenerateItemPool() {
}
// Shopsanity
if (
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)
)
) {
if (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))) {
AddItemsToPool(ItemPool, normalRupees);
} else {
AddItemsToPool(ItemPool, shopsanityRupees); // Shopsanity gets extra large rupees
@ -1222,8 +1117,8 @@ void GenerateItemPool() {
uint8_t bottleCount = 4;
std::vector<RandomizerGet> bottles;
bottles.assign(normalBottles.begin(), normalBottles.end());
ctx->possibleIceTrapModels.push_back(
Rando::StaticData::RetrieveItem(RandomElement(bottles)).GetRandomizerGet()); // Get one random bottle type for ice traps
ctx->possibleIceTrapModels.push_back(Rando::StaticData::RetrieveItem(RandomElement(bottles))
.GetRandomizerGet()); // Get one random bottle type for ice traps
for (uint8_t i = 0; i < bottleCount; i++) {
if (i >= rutoBottles) {
if ((i == bottleCount - 1) &&
@ -1240,7 +1135,8 @@ void GenerateItemPool() {
// add extra songs only if song shuffle is anywhere
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);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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