Merge branch 'develop' into ItemName

This commit is contained in:
Pepper0ni 2025-05-23 22:53:48 +01:00
commit bd6d4cddfc
159 changed files with 1232 additions and 597 deletions

View file

@ -1,7 +1,5 @@
set(CVAR_VSYNC_ENABLED "${CVAR_PREFIX_SETTING}.VsyncEnabled" CACHE STRING "") set(CVAR_VSYNC_ENABLED "${CVAR_PREFIX_SETTING}.VsyncEnabled" CACHE STRING "")
set(CVAR_Z_FIGHTING_MODE "${CVAR_PREFIX_SETTING}.ZFightingMode" CACHE STRING "") set(CVAR_Z_FIGHTING_MODE "${CVAR_PREFIX_SETTING}.ZFightingMode" CACHE STRING "")
set(CVAR_NEW_FILE_DROPPED "${CVAR_PREFIX_GENERAL}.NewFileDropped" CACHE STRING "")
set(CVAR_DROPPED_FILE "${CVAR_PREFIX_GENERAL}.DroppedFile" CACHE STRING "")
set(CVAR_INTERNAL_RESOLUTION "${CVAR_PREFIX_SETTING}.InternalResolution" CACHE STRING "") set(CVAR_INTERNAL_RESOLUTION "${CVAR_PREFIX_SETTING}.InternalResolution" CACHE STRING "")
set(CVAR_MSAA_VALUE "${CVAR_PREFIX_SETTING}.MSAAValue" CACHE STRING "") set(CVAR_MSAA_VALUE "${CVAR_PREFIX_SETTING}.MSAAValue" CACHE STRING "")
set(CVAR_SDL_WINDOWED_FULLSCREEN "${CVAR_PREFIX_SETTING}.SdlWindowedFullscreen" CACHE STRING "") set(CVAR_SDL_WINDOWED_FULLSCREEN "${CVAR_PREFIX_SETTING}.SdlWindowedFullscreen" CACHE STRING "")

View file

@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR)
set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE) set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE)
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
set(CMAKE_C_STANDARD 23 CACHE STRING "The C standard to use")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")

@ -1 +1 @@
Subproject commit 35c3a7e80721e5f5a5260753c14499dc943dd3d8 Subproject commit 6a3f6cd327b99f617b623e5b9a3afeae460aac2b

View file

@ -4,6 +4,7 @@ set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE)
project(soh LANGUAGES C CXX) project(soh LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
set(CMAKE_C_STANDARD 23 CACHE STRING "The C standard to use")
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
enable_language(OBJCXX) enable_language(OBJCXX)
@ -511,10 +512,10 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
-Wno-parentheses -Wno-parentheses
-Wno-narrowing -Wno-narrowing
-Wno-missing-braces -Wno-missing-braces
-Wno-int-conversion
$<$<COMPILE_LANGUAGE:C>: $<$<COMPILE_LANGUAGE:C>:
-Werror-implicit-function-declaration -Werror-implicit-function-declaration
-Wno-incompatible-pointer-types -Wno-incompatible-pointer-types
-Wno-int-conversion
> >
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive> $<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
$<$<COMPILE_LANGUAGE:CXX>: $<$<COMPILE_LANGUAGE:CXX>:
@ -587,11 +588,11 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
-Wno-parentheses -Wno-parentheses
-Wno-narrowing -Wno-narrowing
-Wno-missing-braces -Wno-missing-braces
-Wno-int-conversion
-Wno-implicit-int
$<$<COMPILE_LANGUAGE:C>: $<$<COMPILE_LANGUAGE:C>:
-Werror-implicit-function-declaration -Werror-implicit-function-declaration
-Wno-implicit-int
-Wno-incompatible-pointer-types -Wno-incompatible-pointer-types
-Wno-int-conversion
> >
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive> $<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
$<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion> $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion>

View file

@ -15,7 +15,7 @@ extern "C"
#include <soh/Enhancements/randomizer/randomizer_inf.h> #include <soh/Enhancements/randomizer/randomizer_inf.h>
#if defined(INCLUDE_GAME_PRINTF) && defined(_DEBUG) #if defined(INCLUDE_GAME_PRINTF) && defined(_DEBUG)
#define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, __VA_ARGS__) #define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, ##__VA_ARGS__)
#else #else
#define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, ##__VA_ARGS__) #define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, ##__VA_ARGS__)
#endif #endif
@ -1044,6 +1044,7 @@ VecSph* OLib_Vec3fToVecSph(VecSph* dest, Vec3f* vec);
VecSph* OLib_Vec3fToVecSphGeo(VecSph* arg0, Vec3f* arg1); VecSph* OLib_Vec3fToVecSphGeo(VecSph* arg0, Vec3f* arg1);
VecSph* OLib_Vec3fDiffToVecSphGeo(VecSph* arg0, Vec3f* a, Vec3f* b); VecSph* OLib_Vec3fDiffToVecSphGeo(VecSph* arg0, Vec3f* a, Vec3f* b);
Vec3f* OLib_Vec3fDiffRad(Vec3f* dest, Vec3f* a, Vec3f* b); Vec3f* OLib_Vec3fDiffRad(Vec3f* dest, Vec3f* a, Vec3f* b);
void OnePointCutscene_SetCsCamPoints(Camera* camera, s16 actionParameters, s16 initTimer, CutsceneCameraPoint* atPoints, CutsceneCameraPoint* eyePoints);
s16 OnePointCutscene_Init(PlayState* play, s16 csId, s16 timer, Actor* actor, s16 camIdx); s16 OnePointCutscene_Init(PlayState* play, s16 csId, s16 timer, Actor* actor, s16 camIdx);
s16 OnePointCutscene_EndCutscene(PlayState* play, s16 camIdx); s16 OnePointCutscene_EndCutscene(PlayState* play, s16 camIdx);
s32 OnePointCutscene_Attention(PlayState* play, Actor* actor); s32 OnePointCutscene_Attention(PlayState* play, Actor* actor);
@ -1102,6 +1103,7 @@ void FrameAdvance_Init(FrameAdvanceContext* frameAdvCtx);
s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input); s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input);
u8 PlayerGrounded(Player* player); u8 PlayerGrounded(Player* player);
void Player_SetBootData(PlayState* play, Player* player); void Player_SetBootData(PlayState* play, Player* player);
void Player_StartAnimMovement(PlayState* play, Player* player, s32 flags);
s32 Player_InBlockingCsMode(PlayState* play, Player* player); s32 Player_InBlockingCsMode(PlayState* play, Player* player);
s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction); s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction);
s32 Player_InCsMode(PlayState* play); s32 Player_InCsMode(PlayState* play);
@ -1376,7 +1378,7 @@ void func_800AA0B4();
void func_800AA0F0(void); void func_800AA0F0(void);
u32 func_800AA148(); u32 func_800AA148();
void func_800AA15C(); void func_800AA15C();
void func_800AA16C(); void Rumble_ClearRequests();
void func_800AA178(u32); void func_800AA178(u32);
View* View_New(GraphicsContext* gfxCtx); View* View_New(GraphicsContext* gfxCtx);
void View_Free(View* view); void View_Free(View* view);

View file

@ -544,7 +544,7 @@ typedef enum {
LANGUAGE_MAX LANGUAGE_MAX
} Language; } Language;
#define TODO_TRANSLATE "__Translate_This__" #define TODO_TRANSLATE "TranslateThis"
// TODO get these properties from the textures themselves // TODO get these properties from the textures themselves
#define FONT_CHAR_TEX_WIDTH 16 #define FONT_CHAR_TEX_WIDTH 16

View file

@ -260,9 +260,12 @@ typedef struct SkelAnime {
/* 0x24 */ Vec3s* morphTable; // Table of values used to morph between animations /* 0x24 */ Vec3s* morphTable; // Table of values used to morph between animations
/* 0x28 */ f32 morphWeight; // Weight of the current animation morph as a fraction in [0,1] /* 0x28 */ f32 morphWeight; // Weight of the current animation morph as a fraction in [0,1]
/* 0x2C */ f32 morphRate; // Reciprocal of the number of frames in the morph /* 0x2C */ f32 morphRate; // Reciprocal of the number of frames in the morph
/* 0x30 */ s32 (*update)(); // Can be Loop, Partial loop, Play once, Morph, or Tapered morph. Link only has Loop, Play once, and Morph. /* 0x30 */ union {
s32 (*normal)(struct SkelAnime*); // Can be Loop, Partial loop, Play once, Morph, or Tapered morph
s32 (*link)(struct PlayState*, struct SkelAnime*); // Can be Loop, Play once, or Morph
} update;
/* 0x34 */ s8 initFlags; // Flags used when initializing Link's skeleton /* 0x34 */ s8 initFlags; // Flags used when initializing Link's skeleton
/* 0x35 */ u8 moveFlags; // Flags used for animations that move the actor in worldspace. /* 0x35 */ u8 movementFlags; // Flags used for animations that move the actor in worldspace.
/* 0x36 */ s16 prevRot; // Previous rotation in worldspace. /* 0x36 */ s16 prevRot; // Previous rotation in worldspace.
/* 0x38 */ Vec3s prevTransl; // Previous modelspace translation. /* 0x38 */ Vec3s prevTransl; // Previous modelspace translation.
/* 0x3E */ Vec3s baseTransl; // Base modelspace translation. /* 0x3E */ Vec3s baseTransl; // Base modelspace translation.

View file

@ -61,8 +61,8 @@ std::vector<AltTrapType> getEnabledAddTraps() {
}; };
static void RollRandomTrap(uint32_t seed) { static void RollRandomTrap(uint32_t seed) {
uint32_t finalSeed = uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt); : static_cast<uint32_t>(gSaveContext.ship.stats.fileCreatedAt));
Random_Init(finalSeed); Random_Init(finalSeed);
roll = RandomElement(getEnabledAddTraps()); roll = RandomElement(getEnabledAddTraps());
@ -126,12 +126,12 @@ static void OnPlayerUpdate() {
Play_TriggerRespawn(gPlayState); Play_TriggerRespawn(gPlayState);
break; break;
case ADD_AMMO_TRAP: case ADD_AMMO_TRAP:
AMMO(ITEM_STICK) = AMMO(ITEM_STICK) * 0.5; AMMO(ITEM_STICK) = static_cast<int8_t>(floor(AMMO(ITEM_STICK) * 0.5f));
AMMO(ITEM_NUT) = AMMO(ITEM_NUT) * 0.5; AMMO(ITEM_NUT) = static_cast<int8_t>(floor(AMMO(ITEM_NUT) * 0.5f));
AMMO(ITEM_SLINGSHOT) = AMMO(ITEM_SLINGSHOT) * 0.5; AMMO(ITEM_SLINGSHOT) = static_cast<int8_t>(floor(AMMO(ITEM_SLINGSHOT) * 0.5f));
AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5; AMMO(ITEM_BOW) = static_cast<int8_t>(floor(AMMO(ITEM_BOW) * 0.5f));
AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5; AMMO(ITEM_BOMB) = static_cast<int8_t>(floor(AMMO(ITEM_BOMB) * 0.5f));
AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5; AMMO(ITEM_BOMBCHU) = static_cast<int8_t>(floor(AMMO(ITEM_BOMBCHU) * 0.5f));
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break; break;

View file

@ -0,0 +1,110 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
#include "global.h"
extern "C" {
#include "functions.h"
#include "objects/gameplay_keep/gameplay_keep.h"
extern PlayState* gPlayState;
}
#define CVAR_CRAWL_SPEED_NAME CVAR_ENHANCEMENT("CrawlSpeed")
#define CVAR_CRAWL_SPEED_DEFAULT 1
#define CVAR_CRAWL_SPEED_VALUE CVarGetInteger(CVAR_CRAWL_SPEED_NAME, CVAR_CRAWL_SPEED_DEFAULT)
#define CVAR_GLITCH_AIDING_NAME CVAR_ENHANCEMENT("GlitchAidingCrawlspaces")
#define CVAR_GLITCH_AIDING_DEFAULT 0
#define CVAR_GLITCH_AIDING_VALUE CVarGetInteger(CVAR_GLITCH_AIDING_NAME, CVAR_GLITCH_AIDING_DEFAULT)
extern "C" void ExitCrawlspace(Player* player, PlayState* play) {
LinkAnimationHeader* animExit = (LinkAnimationHeader*)gPlayerAnim_link_child_tunnel_end;
LinkAnimationHeader* animEnter = (LinkAnimationHeader*)gPlayerAnim_link_child_tunnel_start;
if (player->linearVelocity > 0.0f) {
// Leaving a crawlspace forwards
player->actor.shape.rot.y = player->actor.wallYaw + 0x8000;
LinkAnimation_Change(play, &player->skelAnime, animExit, ((CVAR_CRAWL_SPEED_VALUE + 1.0f) / 2.0f), 0.0f,
Animation_GetLastFrame(animExit), ANIMMODE_ONCE, 0.0f);
Player_StartAnimMovement(play, player, 0x9D);
OnePointCutscene_Init(play, 9601, 999, NULL, MAIN_CAM);
} else {
// Leaving a crawlspace backwards
player->actor.shape.rot.y = player->actor.wallYaw;
LinkAnimation_Change(play, &player->skelAnime, animEnter, -1.0f * ((CVAR_CRAWL_SPEED_VALUE + 1.0f) / 2.0f),
Animation_GetLastFrame(animEnter), 0.0f, ANIMMODE_ONCE, 0.0f);
Player_StartAnimMovement(play, player, 0x9D);
OnePointCutscene_Init(play, 9602, 999, NULL, MAIN_CAM);
}
}
extern "C" void ExitCrawlspaceCS(PlayState* play, Camera* csCam, int16_t actionParameters, int16_t initTimer,
CutsceneCameraPoint* atPoints, CutsceneCameraPoint* eyePoints) {
s16 camCrawlTemp = CVAR_CRAWL_SPEED_VALUE;
s16 camCrawlTimer = initTimer / camCrawlTemp;
OnePointCutscene_SetCsCamPoints(csCam, actionParameters | 0x1000, camCrawlTimer, atPoints, eyePoints);
}
extern "C" void EnterCrawlspace(Player* player, PlayState* play) {
LinkAnimationHeader* anim = (LinkAnimationHeader*)gPlayerAnim_link_child_tunnel_start;
LinkAnimation_Change(play, &player->skelAnime, anim, ((CVAR_CRAWL_SPEED_VALUE + 1.0f) / 2.0f), 0.0f,
Animation_GetLastFrame(anim), ANIMMODE_ONCE, 0.0f);
}
extern "C" void IncreaseCrawlSpeed(Player* player, PlayState* play) {
Input* sControlInput = &play->state.input[0];
player->linearVelocity = sControlInput->rel.stick_y * 0.03f * CVAR_CRAWL_SPEED_VALUE;
}
void CrawlSpeed_Register() {
bool shouldRegister = CVAR_CRAWL_SPEED_VALUE > 1;
COND_VB_SHOULD(VB_CRAWL_SPEED_EXIT, shouldRegister, {
Player* player = GET_PLAYER(gPlayState);
bool excludeWellBackroom = (player->actor.world.pos.x > 950.0f) && (player->actor.world.pos.x < 1025.0f) &&
(player->actor.world.pos.z > -1510.0f) && (player->actor.world.pos.z < -1490.0f) &&
gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL;
bool excludeGlitchAiding = CVAR_GLITCH_AIDING_VALUE;
if (excludeGlitchAiding && excludeWellBackroom) {
*should = true;
} else {
ExitCrawlspace(player, gPlayState);
*should = false;
}
});
COND_VB_SHOULD(VB_CRAWL_SPEED_EXIT_CS, shouldRegister, {
Player* player = GET_PLAYER(gPlayState);
Camera* csCam = va_arg(args, Camera*);
s16 csId = va_arg(args, s16);
s16 actionParameters = va_arg(args, s16);
s16 initTimer = va_arg(args, s16);
CutsceneCameraPoint* atPoints = va_arg(args, CutsceneCameraPoint*);
CutsceneCameraPoint* eyePoints = va_arg(args, CutsceneCameraPoint*);
bool excludeWellBackroom = (player->actor.world.pos.x > 950.0f) && (player->actor.world.pos.x < 1025.0f) &&
(player->actor.world.pos.z > -1510.0f) && (player->actor.world.pos.z < -1490.0f) &&
gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL;
bool excludeGlitchAiding = CVAR_GLITCH_AIDING_VALUE;
if (excludeGlitchAiding && excludeWellBackroom) {
*should = true;
} else {
ExitCrawlspaceCS(gPlayState, csCam, actionParameters, initTimer, atPoints, eyePoints);
*should = false;
}
});
COND_VB_SHOULD(VB_CRAWL_SPEED_ENTER, shouldRegister, {
Player* player = GET_PLAYER(gPlayState);
EnterCrawlspace(player, gPlayState);
*should = false;
});
COND_VB_SHOULD(VB_CRAWL_SPEED_INCREASE, shouldRegister, {
Player* player = GET_PLAYER(gPlayState);
IncreaseCrawlSpeed(player, gPlayState);
*should = false;
});
}
static RegisterShipInitFunc initSpeed(CrawlSpeed_Register, { CVAR_CRAWL_SPEED_NAME });

View file

@ -0,0 +1,13 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "z64save.h"
}
void RegisterFasterBeanSkulltula() {
COND_VB_SHOULD(VB_SPAWN_BEAN_SKULLTULA, CVarGetInteger(CVAR_ENHANCEMENT("FasterBeanSkull"), 0),
{ *should = true; });
}
static RegisterShipInitFunc initFunc(RegisterFasterBeanSkulltula, { CVAR_ENHANCEMENT("FasterBeanSkull") });

View file

@ -0,0 +1,19 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "z64save.h"
}
void RegisterFasterEmptyBottle() {
COND_VB_SHOULD(VB_EMPTYING_BOTTLE, CVarGetInteger(CVAR_ENHANCEMENT("FasterBottleEmpty"), 0), {
Player* player = va_arg(args, Player*);
if (player->skelAnime.curFrame <= 60.0f) {
player->skelAnime.playSpeed = 3.0f;
} else {
player->skelAnime.playSpeed = 1.0f;
}
});
}
static RegisterShipInitFunc initFunc(RegisterFasterEmptyBottle, { CVAR_ENHANCEMENT("FasterBottleEmpty") });

View file

@ -41,7 +41,7 @@ void FasterHeavyBlockLift_Register() {
LinkAnimationHeader* anim = va_arg(args, LinkAnimationHeader*); LinkAnimationHeader* anim = va_arg(args, LinkAnimationHeader*);
// Same actor is used for small and large silver rocks, use actor params to identify large ones // Same actor is used for small and large silver rocks, use actor params to identify large ones
bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1; bool isLargeSilverRock = (interactActorId == ACTOR_EN_ISHI) && ((interactRangeActor->params & 1) == 1);
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) && if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) &&
(isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) { (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) {
*should = false; *should = false;

View file

@ -265,6 +265,9 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
} }
} }
auto playingFromMenu = CVarGetInteger(CVAR_AUDIO("Playing"), 0);
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
// Longest text in Audio Editor // Longest text in Audio Editor
ImVec2 columnSize = ImGui::CalcTextSize("Navi - Look/Hey/Watchout (Target Enemy)"); ImVec2 columnSize = ImGui::CalcTextSize("Navi - Look/Hey/Watchout (Target Enemy)");
ImGui::BeginTable(tabId.c_str(), 3, ImGuiTableFlags_SizingFixedFit); ImGui::BeginTable(tabId.c_str(), 3, ImGuiTableFlags_SizingFixedFit);
@ -291,10 +294,13 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
const std::string lockedButton = ICON_FA_LOCK + hiddenKey; const std::string lockedButton = ICON_FA_LOCK + hiddenKey;
const std::string unlockedButton = ICON_FA_UNLOCK + hiddenKey; const std::string unlockedButton = ICON_FA_UNLOCK + hiddenKey;
const int currentValue = CVarGetInteger(cvarKey.c_str(), defaultValue); const int currentValue = CVarGetInteger(cvarKey.c_str(), defaultValue);
const bool isCurrentlyPlaying = currentValue == playingFromMenu || seqData.sequenceId == currentBGM;
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Text("%s", seqData.label.c_str()); ImGui::TextColored(
UIWidgets::ColorValues.at(isCurrentlyPlaying ? UIWidgets::Colors::Yellow : UIWidgets::Colors::White), "%s",
seqData.label.c_str());
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
const int initialValue = map.contains(currentValue) ? currentValue : defaultValue; const int initialValue = map.contains(currentValue) ? currentValue : defaultValue;

View file

@ -111,7 +111,7 @@ const char* BossRush_GetSettingChoiceName(u8 optionIndex, u8 choiceIndex, u8 lan
} }
u8 BossRush_GetSettingOptionsAmount(u8 optionIndex) { u8 BossRush_GetSettingOptionsAmount(u8 optionIndex) {
return BossRushOptions[optionIndex].choices.size(); return static_cast<u8>(BossRushOptions[optionIndex].choices.size());
} }
void BossRush_SpawnBlueWarps(PlayState* play) { void BossRush_SpawnBlueWarps(PlayState* play) {
@ -311,7 +311,8 @@ void BossRush_HandleCompleteBoss(PlayState* play) {
play->sceneNum == SCENE_GANON_BOSS) { play->sceneNum == SCENE_GANON_BOSS) {
gSaveContext.ship.stats.playTimer += 2; gSaveContext.ship.stats.playTimer += 2;
gSaveContext.ship.stats.gameComplete = 1; gSaveContext.ship.stats.gameComplete = 1;
gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_BOSSRUSH_FINISH] = GAMEPLAYSTAT_TOTAL_TIME; gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_BOSSRUSH_FINISH] =
static_cast<uint32_t>(GAMEPLAYSTAT_TOTAL_TIME);
} }
} }

View file

@ -49,14 +49,14 @@ void InputViewer::RenderButton(std::string btnTexture, std::string btnOutlineTex
if (outlineMode == BUTTON_OUTLINE_ALWAYS_SHOWN || (outlineMode == BUTTON_OUTLINE_NOT_PRESSED && !state) || if (outlineMode == BUTTON_OUTLINE_ALWAYS_SHOWN || (outlineMode == BUTTON_OUTLINE_NOT_PRESSED && !state) ||
(outlineMode == BUTTON_OUTLINE_PRESSED && state)) { (outlineMode == BUTTON_OUTLINE_PRESSED && state)) {
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnOutlineTexture), size, ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnOutlineTexture), size,
ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); ImVec2(0, 0), ImVec2(1.0f, 1.0f));
} }
// Render button if pressed // Render button if pressed
if (state) { if (state) {
ImGui::SetCursorPos(pos); ImGui::SetCursorPos(pos);
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnTexture), size, ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnTexture), size,
ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); ImVec2(0, 0), ImVec2(1.0f, 1.0f));
} }
} }
@ -201,7 +201,7 @@ void InputViewer::DrawElement() {
// Background // Background
ImGui::Image( ImGui::Image(
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Input-Viewer-Background"), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Input-Viewer-Background"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f));
} }
// A/B // A/B
@ -345,14 +345,14 @@ void InputViewer::DrawElement() {
// Analog Stick // Analog Stick
const int analogOutlineMode = const int analogOutlineMode =
CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), STICK_MODE_ALWAYS_SHOWN); CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.OutlineMode"), STICK_MODE_ALWAYS_SHOWN);
const float maxStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.Movement"), 12); const int32_t maxStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.Movement"), 12);
if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN || if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN ||
(analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { (analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) {
ImGui::SetNextItemAllowOverlap(); ImGui::SetNextItemAllowOverlap();
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
ImGui::Image( ImGui::Image(
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick Outline"), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick Outline"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f));
} }
const int analogStickMode = const int analogStickMode =
CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), STICK_MODE_ALWAYS_SHOWN); CVarGetInteger(CVAR_INPUT_VIEWER("AnalogStick.VisibilityMode"), STICK_MODE_ALWAYS_SHOWN);
@ -363,11 +363,11 @@ void InputViewer::DrawElement() {
ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale, ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale,
aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale)); aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale));
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"), ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f));
} }
// Right Stick // Right Stick
const float maxRightStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.Movement"), 7); const int32_t maxRightStickDistance = CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.Movement"), 7);
const int rightOutlineMode = const int rightOutlineMode =
CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), STICK_MODE_ALWAYS_HIDDEN); CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.OutlineMode"), STICK_MODE_ALWAYS_HIDDEN);
if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN || if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN ||
@ -376,7 +376,7 @@ void InputViewer::DrawElement() {
ImGui::SetCursorPos(aPos); ImGui::SetCursorPos(aPos);
ImGui::Image( ImGui::Image(
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick Outline"), Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick Outline"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f));
} }
const int rightStickMode = const int rightStickMode =
CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), STICK_MODE_ALWAYS_HIDDEN); CVarGetInteger(CVAR_INPUT_VIEWER("RightStick.VisibilityMode"), STICK_MODE_ALWAYS_HIDDEN);
@ -387,7 +387,7 @@ void InputViewer::DrawElement() {
ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale, ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale,
aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale)); aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale));
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"), ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"),
scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f));
} }
// Analog stick angle text // Analog stick angle text
@ -401,7 +401,7 @@ void InputViewer::DrawElement() {
ImGui::PushFont(ImGui::GetFont()); ImGui::PushFont(ImGui::GetFont());
// Calculate polar R coordinate from X and Y angles, squared to avoid sqrt // Calculate polar R coordinate from X and Y angles, squared to avoid sqrt
const float rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y; const int32_t rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y;
// ESS range // ESS range
const int range1Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Min"), 8); const int range1Min = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Range1.Min"), 8);

View file

@ -50,8 +50,8 @@ void Mouse_HandleFirstPerson(Player* player) {
: 1; : 1;
s8 invertYAxisMulti = CVarGetInteger(CVAR_SETTING("Controls.InvertAimingYAxis"), 1) ? 1 : -1; s8 invertYAxisMulti = CVarGetInteger(CVAR_SETTING("Controls.InvertAimingYAxis"), 1) ? 1 : -1;
if (MOUSE_ENABLED) { if (MOUSE_ENABLED) {
player->actor.focus.rot.y -= mouseCoordRel.x * 6.0f * xAxisMulti * invertXAxisMulti; player->actor.focus.rot.y -= static_cast<int16_t>(mouseCoordRel.x * 6.0f * xAxisMulti * invertXAxisMulti);
player->actor.focus.rot.x += mouseCoordRel.y * 6.0f * yAxisMulti * invertYAxisMulti; player->actor.focus.rot.x += static_cast<int16_t>(mouseCoordRel.y * 6.0f * yAxisMulti * invertYAxisMulti);
} }
} }
@ -59,7 +59,7 @@ void Mouse_RecenterCursor() {
u32 width = GetWindow()->GetWidth(); u32 width = GetWindow()->GetWidth();
u32 height = GetWindow()->GetHeight(); u32 height = GetWindow()->GetHeight();
if (MOUSE_ENABLED) { if (MOUSE_ENABLED) {
GetWindow()->SetMousePos({ (s32)(width / 2), (s32)(height / 2) }); GetWindow()->SetMousePos({ static_cast<s32>(width / 2), static_cast<s32>(height / 2) });
} }
} }
@ -67,8 +67,8 @@ void Mouse_HandleShield(f32* sp50, f32* sp54) {
if (MOUSE_ENABLED) { if (MOUSE_ENABLED) {
s32 width = GetWindow()->GetWidth(); s32 width = GetWindow()->GetWidth();
s32 height = GetWindow()->GetHeight(); s32 height = GetWindow()->GetHeight();
f32 xBound = 7200 / ((f32)width / 2); f32 xBound = 7200 / (width / 2.0f);
f32 yBound = 6000 / ((f32)height / 2); f32 yBound = 6000 / (height / 2.0f);
*sp50 += *sp50 +=
(mouseCoord.x - (width / 2)) * xBound * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 1 : -1); (mouseCoord.x - (width / 2)) * xBound * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 1 : -1);
*sp54 += (mouseCoord.y - (height / 2)) * yBound; *sp54 += (mouseCoord.y - (height / 2)) * yBound;
@ -78,8 +78,8 @@ void Mouse_HandleShield(f32* sp50, f32* sp54) {
} }
static s8 iterMouse = 0; static s8 iterMouse = 0;
static f32 mouseQuickspinX[5] = {}; static s32 mouseQuickspinX[5] = {};
static f32 mouseQuickspinY[5] = {}; static s32 mouseQuickspinY[5] = {};
static u8 quickspinCount = 0; static u8 quickspinCount = 0;
void Mouse_UpdateQuickspinCount() { void Mouse_UpdateQuickspinCount() {
@ -102,9 +102,9 @@ bool Mouse_HandleQuickspin(bool* should, s8* iter2, s8* sp3C) {
for (i = 0; i < 4; i++, iter2++) { for (i = 0; i < 4; i++, iter2++) {
// Calculating angles as per z_lib.c:func_80077D10() // Calculating angles as per z_lib.c:func_80077D10()
f32 relY = mouseQuickspinY[i + 1] - mouseQuickspinY[i]; s32 relY = mouseQuickspinY[i + 1] - mouseQuickspinY[i];
f32 relX = mouseQuickspinX[i + 1] - mouseQuickspinX[i]; s32 relX = mouseQuickspinX[i + 1] - mouseQuickspinX[i];
s16 aTan = Math_Atan2S(relY, -relX); s16 aTan = Math_Atan2S((f32)relY, (f32)-relX);
iterMouse = (u16)(aTan + 0x2000) >> 9; // See z_player.c:Player_ProcessControlStick() iterMouse = (u16)(aTan + 0x2000) >> 9; // See z_player.c:Player_ProcessControlStick()
if ((*iter2 = iterMouse) < 0) { if ((*iter2 = iterMouse) < 0) {
return *should = false; return *should = false;

View file

@ -642,10 +642,14 @@ void SohInputEditorWindow::DrawStickSection(uint8_t port, uint8_t stick, int32_t
ImGui::SameLine(); ImGui::SameLine();
ImGui::BeginGroup(); ImGui::BeginGroup();
DrawStickDirectionLine(ICON_FA_ARROW_UP, port, stick, Ship::UP, color); DrawStickDirectionLine(StringHelper::Sprintf("%s##%d", ICON_FA_ARROW_UP, stick).c_str(), port, stick, Ship::UP,
DrawStickDirectionLine(ICON_FA_ARROW_DOWN, port, stick, Ship::DOWN, color); color);
DrawStickDirectionLine(ICON_FA_ARROW_LEFT, port, stick, Ship::LEFT, color); DrawStickDirectionLine(StringHelper::Sprintf("%s##%d", ICON_FA_ARROW_DOWN, stick).c_str(), port, stick, Ship::DOWN,
DrawStickDirectionLine(ICON_FA_ARROW_RIGHT, port, stick, Ship::RIGHT, color); color);
DrawStickDirectionLine(StringHelper::Sprintf("%s##%d", ICON_FA_ARROW_LEFT, stick).c_str(), port, stick, Ship::LEFT,
color);
DrawStickDirectionLine(StringHelper::Sprintf("%s##%d", ICON_FA_ARROW_RIGHT, stick).c_str(), port, stick,
Ship::RIGHT, color);
ImGui::EndGroup(); ImGui::EndGroup();
ImGui::SetNextItemOpen(true, ImGuiCond_Once); ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode(StringHelper::Sprintf("Analog Stick Options##%d", id).c_str())) { if (ImGui::TreeNode(StringHelper::Sprintf("Analog Stick Options##%d", id).c_str())) {
@ -1335,12 +1339,12 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() {
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
ImGui::BulletText("Disable song detection"); ImGui::BulletText("Disable song detection");
DrawButtonLine(ICON_FA_BAN, 0, BTN_CUSTOM_OCARINA_DISABLE_SONGS); DrawButtonLine(ICON_FA_BAN "##DisableSongDetection", 0, BTN_CUSTOM_OCARINA_DISABLE_SONGS);
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
ImGui::BulletText("Pitch"); ImGui::BulletText("Pitch");
DrawButtonLine(ICON_FA_ARROW_UP, 0, BTN_CUSTOM_OCARINA_PITCH_UP); DrawButtonLine(ICON_FA_ARROW_UP "##Pitch", 0, BTN_CUSTOM_OCARINA_PITCH_UP);
DrawButtonLine(ICON_FA_ARROW_DOWN, 0, BTN_CUSTOM_OCARINA_PITCH_DOWN); DrawButtonLine(ICON_FA_ARROW_DOWN "##Pitch", 0, BTN_CUSTOM_OCARINA_PITCH_DOWN);
if (!CVarGetInteger(CVAR_SETTING("CustomOcarina.Enabled"), 0)) { if (!CVarGetInteger(CVAR_SETTING("CustomOcarina.Enabled"), 0)) {
ImGui::EndDisabled(); ImGui::EndDisabled();

View file

@ -155,12 +155,12 @@ const std::string CustomMessage::GetFrench(MessageFormat format) const {
} }
const std::string CustomMessage::GetForCurrentLanguage(MessageFormat format) const { const std::string CustomMessage::GetForCurrentLanguage(MessageFormat format) const {
return GetForLanguage(((Language)gSaveContext.language == LANGUAGE_JPN) ? LANGUAGE_ENG : gSaveContext.language, return GetForLanguage(
format); ((Language)gSaveContext.language == LANGUAGE_JPN) ? LANGUAGE_ENG : (Language)gSaveContext.language, format);
} }
const std::string CustomMessage::GetForLanguage(uint8_t language, MessageFormat format) const { const std::string CustomMessage::GetForLanguage(uint8_t language, MessageFormat format) const {
std::string output = messages[language] != TODO_TRANSLATE ? messages[language] : messages[LANGUAGE_ENG]; std::string output = !messages[language].starts_with(TODO_TRANSLATE) ? messages[language] : messages[LANGUAGE_ENG];
ProcessMessageFormat(output, format); ProcessMessageFormat(output, format);
return output; return output;
} }

View file

@ -5,6 +5,7 @@
#include "soh/ActorDB.h" #include "soh/ActorDB.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/nametag.h" #include "soh/Enhancements/nametag.h"
#include "soh/ShipInit.hpp"
#include <array> #include <array>
#include <bit> #include <bit>
@ -13,6 +14,7 @@
#include <string> #include <string>
#include <libultraship/bridge.h> #include <libultraship/bridge.h>
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
#include <spdlog/fmt/fmt.h>
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h" #include "soh/cvar_prefixes.h"
@ -31,6 +33,10 @@ extern PlayState* gPlayState;
#define DEKUNUTS_FLOWER 10 #define DEKUNUTS_FLOWER 10
#define DEBUG_ACTOR_NAMETAG_TAG "debug_actor_viewer" #define DEBUG_ACTOR_NAMETAG_TAG "debug_actor_viewer"
#define CVAR_ACTOR_NAME_TAGS(val) CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags." val)
#define CVAR_ACTOR_NAME_TAGS_ENABLED_NAME CVAR_ACTOR_NAME_TAGS("Enabled")
#define CVAR_ACTOR_NAME_TAGS_ENABLED CVarGetInteger(CVAR_ACTOR_NAME_TAGS("Enabled"), 0)
typedef struct { typedef struct {
u16 id; u16 id;
u16 params; u16 params;
@ -67,6 +73,10 @@ const std::string GetActorDescription(u16 id) {
return ActorDB::Instance->RetrieveEntry(id).entry.valid ? ActorDB::Instance->RetrieveEntry(id).entry.desc : "???"; return ActorDB::Instance->RetrieveEntry(id).entry.valid ? ActorDB::Instance->RetrieveEntry(id).entry.desc : "???";
} }
const std::string GetActorDebugName(u16 id) {
return ActorDB::Instance->RetrieveEntry(id).entry.valid ? ActorDB::Instance->RetrieveEntry(id).entry.name : "???";
}
template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) { template <typename T> void DrawGroupWithBorder(T&& drawFunc, std::string section) {
// First group encapsulates the inner portion and border // First group encapsulates the inner portion and border
ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0), ImGui::BeginChild(std::string("##" + section).c_str(), ImVec2(0, 0),
@ -812,25 +822,37 @@ std::vector<u16> GetActorsWithDescriptionContainingString(std::string s) {
} }
void ActorViewer_AddTagForActor(Actor* actor) { void ActorViewer_AddTagForActor(Actor* actor) {
int val = CVarGetInteger(CVAR_DEVELOPER_TOOLS("ActorViewer.NameTags"), ACTORVIEWER_NAMETAGS_NONE); if (!CVarGetInteger(CVAR_ACTOR_NAME_TAGS("Enabled"), 0)) {
auto entry = ActorDB::Instance->RetrieveEntry(actor->id); return;
std::string tag;
if (val > 0 && entry.entry.valid) {
switch (val) {
case ACTORVIEWER_NAMETAGS_DESC:
tag = entry.desc;
break;
case ACTORVIEWER_NAMETAGS_NAME:
tag = entry.name;
break;
case ACTORVIEWER_NAMETAGS_BOTH:
tag = entry.name + '\n' + entry.desc;
break;
} }
NameTag_RegisterForActorWithOptions(actor, tag.c_str(), { .tag = DEBUG_ACTOR_NAMETAG_TAG }); std::vector<std::string> parts;
if (CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayID"), 0)) {
parts.push_back(GetActorDebugName(actor->id));
} }
if (CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayDescription"), 0)) {
parts.push_back(GetActorDescription(actor->id));
}
if (CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayCategory"), 0)) {
parts.push_back(acMapping[actor->category]);
}
if (CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayParams"), 0)) {
parts.push_back(fmt::format("0x{:04X} ({})", (u16)actor->params, actor->params));
}
std::string tag = "";
for (size_t i = 0; i < parts.size(); i++) {
if (i != 0) {
tag += "\n";
}
tag += parts.at(i);
}
bool withZBuffer = CVarGetInteger(CVAR_ACTOR_NAME_TAGS("WithZBuffer"), 0);
NameTag_RegisterForActorWithOptions(actor, tag.c_str(),
{ .tag = DEBUG_ACTOR_NAMETAG_TAG, .noZBuffer = !withZBuffer });
} }
void ActorViewer_AddTagForAllActors() { void ActorViewer_AddTagForAllActors() {
@ -881,6 +903,57 @@ void ActorViewerWindow::DrawElement() {
} }
lastSceneId = gPlayState->sceneNum; lastSceneId = gPlayState->sceneNum;
if (ImGui::BeginChild("options", ImVec2(0, 0), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) {
bool toggled = false;
bool optionChange = false;
ImGui::SeparatorText("Options");
toggled = UIWidgets::CVarCheckbox("Actor Name Tags", CVAR_ACTOR_NAME_TAGS("Enabled"),
{ { .tooltip = "Adds \"name tags\" above actors for identification" } });
ImGui::SameLine();
UIWidgets::Button("Display Items", { { .tooltip = "Click to add display items on the name tags" } });
if (ImGui::BeginPopupContextItem(nullptr, ImGuiPopupFlags_MouseButtonLeft | ImGuiPopupFlags_NoReopen)) {
optionChange |= UIWidgets::CVarCheckbox("ID", CVAR_ACTOR_NAME_TAGS("DisplayID"));
optionChange |= UIWidgets::CVarCheckbox("Description", CVAR_ACTOR_NAME_TAGS("DisplayDescription"));
optionChange |= UIWidgets::CVarCheckbox("Category", CVAR_ACTOR_NAME_TAGS("DisplayCategory"));
optionChange |= UIWidgets::CVarCheckbox("Params", CVAR_ACTOR_NAME_TAGS("DisplayParams"));
ImGui::EndPopup();
}
optionChange |= UIWidgets::CVarCheckbox(
"Name tags with Z-Buffer", CVAR_ACTOR_NAME_TAGS("WithZBuffer"),
{ { .tooltip = "Allow name tags to be obstructed when behind geometry and actors" } });
if (toggled || optionChange) {
bool tagsEnabled = CVarGetInteger(CVAR_ACTOR_NAME_TAGS("Enabled"), 0);
bool noOptionsEnabled = !CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayID"), 0) &&
!CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayDescription"), 0) &&
!CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayCategory"), 0) &&
!CVarGetInteger(CVAR_ACTOR_NAME_TAGS("DisplayParams"), 0);
// Save the user an extra click and prevent adding "empty" tags by enabling,
// disabling, or setting an option based on what changed
if (tagsEnabled && noOptionsEnabled) {
if (toggled) {
CVarSetInteger(CVAR_ACTOR_NAME_TAGS("DisplayID"), 1);
} else {
CVarSetInteger(CVAR_ACTOR_NAME_TAGS("Enabled"), 0);
}
} else if (optionChange && !tagsEnabled && !noOptionsEnabled) {
CVarSetInteger(CVAR_ACTOR_NAME_TAGS("Enabled"), 1);
}
NameTag_RemoveAllByTag(DEBUG_ACTOR_NAMETAG_TAG);
ActorViewer_AddTagForAllActors();
}
}
ImGui::EndChild();
PushStyleCombobox(THEME_COLOR); PushStyleCombobox(THEME_COLOR);
if (ImGui::BeginCombo("Actor Type", acMapping[category])) { if (ImGui::BeginCombo("Actor Type", acMapping[category])) {
for (int i = 0; i < acMapping.size(); i++) { for (int i = 0; i < acMapping.size(); i++) {
@ -1160,20 +1233,6 @@ void ActorViewerWindow::DrawElement() {
ImGui::TreePop(); ImGui::TreePop();
} }
PopStyleHeader(); PopStyleHeader();
static std::unordered_map<int32_t, const char*> nameTagOptions = {
{ 0, "None" },
{ 1, "Short Description" },
{ 2, "Actor ID" },
{ 3, "Both" },
};
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();
}
} else { } else {
ImGui::Text("Global Context needed for actor info!"); ImGui::Text("Global Context needed for actor info!");
if (needs_reset) { if (needs_reset) {
@ -1190,9 +1249,9 @@ void ActorViewerWindow::DrawElement() {
ImGui::EndDisabled(); ImGui::EndDisabled();
} }
void ActorViewerWindow::InitElement() { void ActorViewer_RegisterNameTagHooks() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) { COND_HOOK(OnActorInit, CVAR_ACTOR_NAME_TAGS_ENABLED,
Actor* actor = static_cast<Actor*>(refActor); [](void* actor) { ActorViewer_AddTagForActor(static_cast<Actor*>(actor)); });
ActorViewer_AddTagForActor(actor);
});
} }
RegisterShipInitFunc nametagInit(ActorViewer_RegisterNameTagHooks, { CVAR_ACTOR_NAME_TAGS_ENABLED_NAME });

View file

@ -7,6 +7,6 @@ class ActorViewerWindow final : public Ship::GuiWindow {
using GuiWindow::GuiWindow; using GuiWindow::GuiWindow;
void DrawElement() override; void DrawElement() override;
void InitElement() override; void InitElement() override{};
void UpdateElement() override{}; void UpdateElement() override{};
}; };

View file

@ -29,6 +29,7 @@ DEFINE_HOOK(OnShopSlotChange, (uint8_t cursorIndex, int16_t price));
DEFINE_HOOK(OnActorInit, (void* actor)); DEFINE_HOOK(OnActorInit, (void* actor));
DEFINE_HOOK(OnActorUpdate, (void* actor)); DEFINE_HOOK(OnActorUpdate, (void* actor));
DEFINE_HOOK(OnActorKill, (void* actor)); DEFINE_HOOK(OnActorKill, (void* actor));
DEFINE_HOOK(OnActorDestroy, (void* actor));
DEFINE_HOOK(OnEnemyDefeat, (void* actor)); DEFINE_HOOK(OnEnemyDefeat, (void* actor));
DEFINE_HOOK(OnBossDefeat, (void* actor)); DEFINE_HOOK(OnBossDefeat, (void* actor));
DEFINE_HOOK(OnTimestamp, (u8 item)); DEFINE_HOOK(OnTimestamp, (u8 item));

View file

@ -122,6 +122,13 @@ void GameInteractor_ExecuteOnActorKill(void* actor) {
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorKill>(actor); GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorKill>(actor);
} }
void GameInteractor_ExecuteOnActorDestroy(void* actor) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnActorDestroy>(actor);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnActorDestroy>(((Actor*)actor)->id, actor);
GameInteractor::Instance->ExecuteHooksForPtr<GameInteractor::OnActorDestroy>((uintptr_t)actor, actor);
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorDestroy>(actor);
}
void GameInteractor_ExecuteOnEnemyDefeat(void* actor) { void GameInteractor_ExecuteOnEnemyDefeat(void* actor) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnEnemyDefeat>(actor); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnEnemyDefeat>(actor);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnEnemyDefeat>(((Actor*)actor)->id, actor); GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnEnemyDefeat>(((Actor*)actor)->id, actor);

View file

@ -31,6 +31,7 @@ void GameInteractor_ExecuteOnCuccoOrChickenHatch();
void GameInteractor_ExecuteOnActorInit(void* actor); void GameInteractor_ExecuteOnActorInit(void* actor);
void GameInteractor_ExecuteOnActorUpdate(void* actor); void GameInteractor_ExecuteOnActorUpdate(void* actor);
void GameInteractor_ExecuteOnActorKill(void* actor); void GameInteractor_ExecuteOnActorKill(void* actor);
void GameInteractor_ExecuteOnActorDestroy(void* actor);
void GameInteractor_ExecuteOnEnemyDefeat(void* actor); void GameInteractor_ExecuteOnEnemyDefeat(void* actor);
void GameInteractor_ExecuteOnBossDefeat(void* actor); void GameInteractor_ExecuteOnBossDefeat(void* actor);
void GameInteractor_ExecuteOnTimestamp(u8 item); void GameInteractor_ExecuteOnTimestamp(u8 item);

View file

@ -112,7 +112,7 @@ void GameInteractor::RawAction::FreezePlayer() {
void GameInteractor::RawAction::BurnPlayer() { void GameInteractor::RawAction::BurnPlayer() {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
for (int i = 0; i < 18; i++) { for (int i = 0; i < 18; i++) {
player->bodyFlameTimers[i] = Rand_S16Offset(0, 200); player->bodyFlameTimers[i] = static_cast<uint8_t>(Rand_S16Offset(0, 200));
} }
player->bodyIsBurning = true; player->bodyIsBurning = true;
func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0); func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0);
@ -559,7 +559,7 @@ void GameInteractor::RawAction::SetRandomWind(bool active) {
GameInteractor::State::RandomWindActive = 0; GameInteractor::State::RandomWindActive = 0;
GameInteractor::State::RandomWindSecondsSinceLastDirectionChange = 0; GameInteractor::State::RandomWindSecondsSinceLastDirectionChange = 0;
player->pushedSpeed = 0.0f; player->pushedSpeed = 0.0f;
player->pushedYaw = 0.0f; player->pushedYaw = 0;
} }
} }
@ -617,7 +617,7 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset
} }
// Generate point in random angle with a radius. // Generate point in random angle with a radius.
float angle = Random(0, 2 * M_PI); float angle = static_cast<float>(RandomDouble() * 2 * M_PI);
float radius = 150; float radius = 150;
float posXOffset = radius * cos(angle); float posXOffset = radius * cos(angle);
float posZOffset = radius * sin(angle); float posZOffset = radius * sin(angle);

View file

@ -294,6 +294,43 @@ typedef enum {
// - `*ObjKibako2` // - `*ObjKibako2`
VB_CRATE_SETUP_DRAW, VB_CRATE_SETUP_DRAW,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - None
VB_CRAWL_SPEED_ENTER,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - None
VB_CRAWL_SPEED_EXIT,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*Camera`
// - 'int16_t' (csId)
// - 'int16_t' (actionParameters)
// - 'int16_t' (initTimer)
// - 'CutsceneCameraPoint*' (atPoints)
// - 'CutsceneCameraPoint*' (eyePoints)
VB_CRAWL_SPEED_EXIT_CS,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - None
VB_CRAWL_SPEED_INCREASE,
// #### `result` // #### `result`
// ```c // ```c
// !Flags_GetItemGetInf(ITEMGETINF_1C) // !Flags_GetItemGetInf(ITEMGETINF_1C)
@ -425,6 +462,14 @@ typedef enum {
// - `*int16_t` (item id) // - `*int16_t` (item id)
VB_DRAW_AMMO_COUNT, VB_DRAW_AMMO_COUNT,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - Player*
VB_EMPTYING_BOTTLE,
// #### `result` // #### `result`
// ```c // ```c
// (Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play) // (Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)
@ -474,6 +519,14 @@ typedef enum {
// - `*BgHeavyBlock` // - `*BgHeavyBlock`
VB_FREEZE_LINK_FOR_BLOCK_THROW, VB_FREEZE_LINK_FOR_BLOCK_THROW,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - None
VB_FREEZE_LINK_FOR_FOREST_PILLARS,
// #### `result` // #### `result`
// ```c // ```c
// true // true
@ -1358,6 +1411,14 @@ typedef enum {
// - `*BgTreemouth` // - `*BgTreemouth`
VB_PLAY_DEKU_TREE_INTRO_CS, VB_PLAY_DEKU_TREE_INTRO_CS,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*DemoKekkai`
VB_PLAY_DISPEL_BARRIER_CS,
// #### `result` // #### `result`
// ```c // ```c
// true // true
@ -1422,6 +1483,15 @@ typedef enum {
// - None // - None
VB_PLAY_FIRE_ARROW_CS, VB_PLAY_FIRE_ARROW_CS,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*EnHeishi2`
// - `bool` (clearCamera - true if the code clears a sub-camera, false otherwise)
VB_PLAY_GATE_OPENING_OR_CLOSING_CS,
// #### `result` // #### `result`
// ```c // ```c
// true // true
@ -1790,6 +1860,14 @@ typedef enum {
// - `*ObjBean` // - `*ObjBean`
VB_SPAWN_BEAN_STALK_FAIRIES, VB_SPAWN_BEAN_STALK_FAIRIES,
// #### `result`
// ```c
// this->timer >= 60
// ```
// #### `args`
// - `None`
VB_SPAWN_BEAN_SKULLTULA,
// #### `result` // #### `result`
// ```c // ```c
// true // true

View file

@ -12,7 +12,6 @@
#include "soh/Enhancements/randomizer/3drando/random.hpp" #include "soh/Enhancements/randomizer/3drando/random.hpp"
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h" #include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
#include <soh/Enhancements/item-tables/ItemTableManager.h> #include <soh/Enhancements/item-tables/ItemTableManager.h>
#include "soh/Enhancements/nametag.h"
#include "soh/Enhancements/timesaver_hook_handlers.h" #include "soh/Enhancements/timesaver_hook_handlers.h"
#include "soh/Enhancements/TimeSavers/TimeSavers.h" #include "soh/Enhancements/TimeSavers/TimeSavers.h"
#include "soh/Enhancements/randomizer/hook_handlers.h" #include "soh/Enhancements/randomizer/hook_handlers.h"
@ -1090,7 +1089,6 @@ void InitMods() {
RegisterRandomizedEnemySizes(); RegisterRandomizedEnemySizes();
RegisterOpenAllHours(); RegisterOpenAllHours();
RegisterToTMedallions(); RegisterToTMedallions();
NameTag_RegisterHooks();
RegisterFloorSwitchesHook(); RegisterFloorSwitchesHook();
RegisterPatchHandHandler(); RegisterPatchHandHandler();
RegisterHurtContainerModeHandler(); RegisterHurtContainerModeHandler();

View file

@ -5,7 +5,7 @@
#include "soh/frame_interpolation.h" #include "soh/frame_interpolation.h"
#include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h" #include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/OTRGlobals.h" #include "soh/ShipUtils.h"
extern "C" { extern "C" {
#include "z64.h" #include "z64.h"
@ -26,12 +26,16 @@ typedef struct {
int16_t height; // Textbox height int16_t height; // Textbox height
int16_t width; // Textbox width int16_t width; // Textbox width
int16_t yOffset; // Addition Y offset int16_t yOffset; // Addition Y offset
uint8_t noZBuffer; // Allow rendering over geometry
Mtx* mtx; // Allocated Mtx for rendering Mtx* mtx; // Allocated Mtx for rendering
Vtx* vtx; // Allocated Vtx for rendering Vtx* vtx; // Allocated Vtx for rendering
} NameTag; } NameTag;
static std::vector<NameTag> nameTags; static std::vector<NameTag> nameTags;
static std::vector<Gfx> nameTagDl; static std::vector<Gfx> nameTagDl;
static bool sMirrorWorldActive = false;
void NameTag_RegisterHooks();
void FreeNameTag(NameTag* nameTag) { void FreeNameTag(NameTag* nameTag) {
if (nameTag->vtx != nullptr) { if (nameTag->vtx != nullptr) {
@ -51,14 +55,14 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
} }
// Name tag is too far away to meaningfully read, don't bother rendering it // Name tag is too far away to meaningfully read, don't bother rendering it
if (nameTag->actor->xyzDistToPlayerSq > 200000.0f) { if (nameTag->actor->xyzDistToPlayerSq > 440000.0f) {
return; return;
} }
// Fade out name tags that are far away // Fade out name tags that are far away
float alpha = 1.0f; float alpha = 1.0f;
if (nameTag->actor->xyzDistToPlayerSq > 160000.0f) { if (nameTag->actor->xyzDistToPlayerSq > 360000.0f) {
alpha = (200000.0f - nameTag->actor->xyzDistToPlayerSq) / 40000.0f; alpha = (440000.0f - nameTag->actor->xyzDistToPlayerSq) / 80000.0f;
} }
float scale = 75.0f / 100.f; float scale = 75.0f / 100.f;
@ -79,7 +83,7 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
textColor = CVarGetColor(CVAR_COSMETIC("HUD.NameTagActorText.Value"), textColor); textColor = CVarGetColor(CVAR_COSMETIC("HUD.NameTagActorText.Value"), textColor);
} }
FrameInterpolation_RecordOpenChild(nameTag->actor, 10); FrameInterpolation_RecordOpenChild(nameTag->actor, 0);
// Prefer the highest between world position and focus position if targetable // Prefer the highest between world position and focus position if targetable
float posY = nameTag->actor->world.pos.y; float posY = nameTag->actor->world.pos.y;
@ -92,7 +96,7 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
// Set position, billboard effect, scale (with mirror mode), then center nametag // Set position, billboard effect, scale (with mirror mode), then center nametag
Matrix_Translate(nameTag->actor->world.pos.x, posY, nameTag->actor->world.pos.z, MTXMODE_NEW); Matrix_Translate(nameTag->actor->world.pos.x, posY, nameTag->actor->world.pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&play->billboardMtxF); Matrix_ReplaceRotation(&play->billboardMtxF);
Matrix_Scale(scale * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1), -scale, 1.0f, MTXMODE_APPLY); Matrix_Scale(scale * (sMirrorWorldActive ? -1.0f : 1.0f), -scale, 1.0f, MTXMODE_APPLY);
Matrix_Translate(-(float)nameTag->width / 2, -nameTag->height, 0, MTXMODE_APPLY); Matrix_Translate(-(float)nameTag->width / 2, -nameTag->height, 0, MTXMODE_APPLY);
Matrix_ToMtx(nameTag->mtx, (char*)__FILE__, __LINE__); Matrix_ToMtx(nameTag->mtx, (char*)__FILE__, __LINE__);
@ -154,15 +158,27 @@ void DrawNameTags() {
OPEN_DISPS(gPlayState->state.gfxCtx); OPEN_DISPS(gPlayState->state.gfxCtx);
// Setup before rendering name tags // Setup before rendering name tags
Gfx_SetupDL_38Xlu(gPlayState->state.gfxCtx); POLY_XLU_DISP = Gfx_SetupDL_39(POLY_XLU_DISP);
nameTagDl.push_back(gsDPSetAlphaDither(G_AD_DISABLE));
nameTagDl.push_back(gsSPClearGeometryMode(G_SHADE));
nameTagDl.push_back(gsDPSetAlphaCompare(G_AC_NONE));
nameTagDl.push_back( nameTagDl.push_back(
gsDPSetCombineLERP(0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0)); gsDPSetCombineLERP(0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0));
bool zbufferEnabled = false;
// Add all the name tags // Add all the name tags
for (const auto& nameTag : nameTags) { for (const auto& nameTag : nameTags) {
// Toggle ZBuffer mode based on last state and next tag
if (zbufferEnabled == nameTag.noZBuffer) {
if (nameTag.noZBuffer) {
nameTagDl.push_back(gsSPClearGeometryMode(G_ZBUFFER));
zbufferEnabled = false;
} else {
nameTagDl.push_back(gsSPSetGeometryMode(G_ZBUFFER));
zbufferEnabled = true;
}
}
DrawNameTag(gPlayState, &nameTag); DrawNameTag(gPlayState, &nameTag);
} }
@ -189,22 +205,22 @@ void UpdateNameTags() {
return aDistToCamera > bDistToCamera; return aDistToCamera > bDistToCamera;
}); });
sMirrorWorldActive = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0);
} }
extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* text, NameTagOptions options) { extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* text, NameTagOptions options) {
std::string processedText = std::string(Interface_ReplaceSpecialCharacters((char*)text)); std::string processedText = std::string(Interface_ReplaceSpecialCharacters((char*)text));
// Strip out unsupported characters // Strip out unsupported characters
processedText.erase(std::remove_if(processedText.begin(), processedText.end(),
[](const char& c) {
// 172 is max supported texture for the in-game font system, // 172 is max supported texture for the in-game font system,
// and filter anything less than a space but not the newline or nul // and filter anything less than a space but not the newline or nul characters
// characters processedText.erase(
return (unsigned char)c > 172 || (c < ' ' && c != '\n' && c != '\0'); std::remove_if(processedText.begin(), processedText.end(),
}), [](const char& c) { return (uint8_t)c > 172 || (c < ' ' && c != '\n' && c != '\0'); }),
processedText.end()); processedText.end());
int16_t numChar = processedText.length(); size_t numChar = processedText.length();
int16_t numLines = 1; int16_t numLines = 1;
int16_t offsetX = 0; int16_t offsetX = 0;
int16_t maxOffsetX = 0; int16_t maxOffsetX = 0;
@ -213,7 +229,7 @@ extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* te
Vtx* vertices = (Vtx*)calloc(sizeof(Vtx[4]), numChar + 1); Vtx* vertices = (Vtx*)calloc(sizeof(Vtx[4]), numChar + 1);
// Set all the char vtx first to get the total size for the textbox // Set all the char vtx first to get the total size for the textbox
for (int16_t i = 0; i < numChar; i++) { for (size_t i = 0; i < numChar; i++) {
if (processedText[i] == '\n') { if (processedText[i] == '\n') {
offsetX = 0; offsetX = 0;
numLines++; numLines++;
@ -249,10 +265,13 @@ extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* te
nameTag.height = height; nameTag.height = height;
nameTag.width = width; nameTag.width = width;
nameTag.yOffset = options.yOffset; nameTag.yOffset = options.yOffset;
nameTag.noZBuffer = options.noZBuffer;
nameTag.mtx = new Mtx(); nameTag.mtx = new Mtx();
nameTag.vtx = vertices; nameTag.vtx = vertices;
nameTags.push_back(nameTag); nameTags.push_back(nameTag);
NameTag_RegisterHooks();
} }
extern "C" void NameTag_RegisterForActor(Actor* actor, const char* text) { extern "C" void NameTag_RegisterForActor(Actor* actor, const char* text) {
@ -268,6 +287,8 @@ extern "C" void NameTag_RemoveAllForActor(Actor* actor) {
it++; it++;
} }
} }
NameTag_RegisterHooks();
} }
extern "C" void NameTag_RemoveAllByTag(const char* tag) { extern "C" void NameTag_RemoveAllByTag(const char* tag) {
@ -279,6 +300,8 @@ extern "C" void NameTag_RemoveAllByTag(const char* tag) {
it++; it++;
} }
} }
NameTag_RegisterHooks();
} }
void RemoveAllNameTags() { void RemoveAllNameTags() {
@ -287,23 +310,49 @@ void RemoveAllNameTags() {
} }
nameTags.clear(); nameTags.clear();
NameTag_RegisterHooks();
} }
void NameTag_RegisterHooks() {
static HOOK_ID gameStatUpdateHookID = 0;
static HOOK_ID drawHookID = 0;
static HOOK_ID playDestroyHookID = 0;
static HOOK_ID actorDestroyHookID = 0;
static bool sRegisteredHooks = false; static bool sRegisteredHooks = false;
void NameTag_RegisterHooks() { // Hooks already (un)registered based on nametags
if (sRegisteredHooks) { if ((nameTags.size() > 0) == sRegisteredHooks) {
return;
}
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnGameFrameUpdate>(gameStatUpdateHookID);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayDrawEnd>(drawHookID);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayDestroy>(playDestroyHookID);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorDestroy>(actorDestroyHookID);
gameStatUpdateHookID = 0;
drawHookID = 0;
playDestroyHookID = 0;
actorDestroyHookID = 0;
sRegisteredHooks = false;
if (nameTags.size() == 0) {
return; return;
} }
sRegisteredHooks = true; sRegisteredHooks = true;
// Reorder tags every frame to mimic depth rendering // Reorder tags every frame to mimic depth rendering
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() { UpdateNameTags(); }); gameStatUpdateHookID =
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(UpdateNameTags);
// Render name tags at the end of player draw to avoid overflowing the display buffers // Render name tags at the end of the Play World drawing
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayDrawEnd>([]() { DrawNameTags(); }); drawHookID = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayDrawEnd>(DrawNameTags);
// Remove all name tags on play state destroy as all actors are removed anyways // Remove all name tags on play state destroy as all actors are removed anyways
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayDestroy>([]() { RemoveAllNameTags(); }); playDestroyHookID = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayDestroy>(RemoveAllNameTags);
// Remove all name tags for actor on destroy
actorDestroyHookID = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorDestroy>(
[](void* actor) { NameTag_RemoveAllForActor((Actor*)actor); });
} }

View file

@ -1,11 +1,16 @@
#ifndef _NAMETAG_H_ #ifndef NAMETAG_H
#define _NAMETAG_H_ #define NAMETAG_H
#include <z64.h>
#include <libultraship/color.h>
#include <libultraship/libultra.h>
struct Actor;
typedef struct { typedef struct {
const char* tag; // Tag identifier to filter/remove multiple tags const char* tag; // Tag identifier to filter/remove multiple tags
int16_t yOffset; // Additional Y offset to apply for the name tag int16_t yOffset; // Additional Y offset to apply for the name tag
Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0 Color_RGBA8 textColor; // Text color override. Global color is used if alpha is 0
uint8_t noZBuffer; // Allow rendering over geometry
} NameTagOptions; } NameTagOptions;
// Register required hooks for nametags on startup // Register required hooks for nametags on startup
@ -28,4 +33,4 @@ void NameTag_RemoveAllByTag(const char* tag);
} }
#endif #endif
#endif // _NAMETAG_H_ #endif // NAMETAG_H

View file

@ -625,6 +625,8 @@ void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAcce
if (ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF)) { if (ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF)) {
Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect(); Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect();
} }
RegionTable(RR_ROOT)->adultNight = true;
RegionTable(RR_ROOT)->adultDay = true;
} else { } else {
ApplyAllAdvancmentItems(); ApplyAllAdvancmentItems();
} }
@ -710,11 +712,11 @@ static void PareDownPlaythrough() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
std::vector<RandomizerCheck> toAddBackItem; std::vector<RandomizerCheck> toAddBackItem;
// Start at sphere before Ganon's and count down // Start at sphere before Ganon's and count down
for (int i = ctx->playthroughLocations.size() - 2; i >= 0; i--) { for (int32_t i = static_cast<int32_t>(ctx->playthroughLocations.size()) - 2; i >= 0; i--) {
// Check each item location in sphere // Check each item location in sphere
std::vector<int> erasableIndices; std::vector<int> erasableIndices;
std::vector<RandomizerCheck> sphere = ctx->playthroughLocations.at(i); std::vector<RandomizerCheck> sphere = ctx->playthroughLocations.at(i);
for (int j = sphere.size() - 1; j >= 0; j--) { for (int32_t j = static_cast<int32_t>(sphere.size()) - 1; j >= 0; j--) {
RandomizerCheck loc = sphere.at(j); RandomizerCheck loc = sphere.at(j);
RandomizerGet locGet = ctx->GetItemLocation(loc)->GetPlacedRandomizerGet(); // Copy out item RandomizerGet locGet = ctx->GetItemLocation(loc)->GetPlacedRandomizerGet(); // Copy out item

View file

@ -2462,13 +2462,13 @@ void StaticData::HintTable_Init() {
/*german*/ "ein abgelegener Ort", /*german*/ "ein abgelegener Ort",
/*french*/ "un lieu isolé")); /*french*/ "un lieu isolé"));
hintTextTable[RHT_DUNGEON_ORDINARY] = HintText(CustomMessage(" It's ordinary.", hintTextTable[RHT_DUNGEON_ORDINARY] = HintText(CustomMessage("&It's %gordinary%w.",
/*german*/ "&Sieht aus wie immer.", /*german*/ "&Sieht aus %gwie immer%w.",
/*french*/ "&Elle vous semble %rordinaire%w.")); /*french*/ "&Elle vous semble %gordinaire%w."));
hintTextTable[RHT_DUNGEON_MASTERFUL] = HintText(CustomMessage(" It's masterful!", hintTextTable[RHT_DUNGEON_MASTERFUL] = HintText(CustomMessage("&It's %rmasterful%w!",
/*german*/ "&Man kann darauf die Worte&%r\"Master Quest\"%w entziffern...", /*german*/ "&Man kann darauf die Worte %r\"Master_Quest\"%w entziffern...",
/*french*/ "&Étrange... les mots %r\"Master&Quest\"%w sont gravés dessus.")); /*french*/ "&Étrange... les mots %r\"Master_Quest\"%w sont gravés dessus."));
// clang-format on // clang-format on
} }

View file

@ -69,11 +69,11 @@ const CustomMessage& HintText::GetAmbiguous(uint8_t selection) const {
} }
uint8_t HintText::GetAmbiguousSize() const { uint8_t HintText::GetAmbiguousSize() const {
return ambiguousText.size(); return static_cast<uint8_t>(ambiguousText.size());
} }
uint8_t HintText::GetObscureSize() const { uint8_t HintText::GetObscureSize() const {
return obscureText.size(); return static_cast<uint8_t>(obscureText.size());
} }
const CustomMessage& HintText::GetHintMessage(uint8_t selection) const { const CustomMessage& HintText::GetHintMessage(uint8_t selection) const {
@ -604,7 +604,7 @@ static void DistributeHints(std::vector<uint8_t>& selected, size_t stoneCount,
} }
// if stones are left, assign junk to every remaining stone as a fallback. // if stones are left, assign junk to every remaining stone as a fallback.
if (stoneCount > 0) { if (stoneCount > 0) {
selected[selected.size() - 1] += stoneCount; selected[static_cast<uint8_t>(selected.size()) - 1] += static_cast<uint8_t>(stoneCount);
} }
} }

View file

@ -325,7 +325,7 @@ RandomizerGet GetJunkItem() {
return RandomElement(JunkPoolItems); return RandomElement(JunkPoolItems);
} }
// Ice Trap is the last item in JunkPoolItems, so subtract 1 to never hit that index // Ice Trap is the last item in JunkPoolItems, so subtract 1 to never hit that index
uint8_t idx = Random(0, JunkPoolItems.size() - 1); uint8_t idx = Random(0, static_cast<uint32_t>(JunkPoolItems.size()) - 1);
return JunkPoolItems[idx]; return JunkPoolItems[idx];
} }

View file

@ -27,7 +27,7 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
ResetPerformanceTimers(); ResetPerformanceTimers();
StartPerformanceTimer(PT_WHOLE_SEED); StartPerformanceTimer(PT_WHOLE_SEED);
srand(time(NULL)); srand(static_cast<uint32_t>(time(NULL)));
// if a blank seed was entered, make a random one // if a blank seed was entered, make a random one
if (seedInput.empty()) { if (seedInput.empty()) {
seedInput = std::to_string(rand() % 0xFFFFFFFF); seedInput = std::to_string(rand() % 0xFFFFFFFF);
@ -35,7 +35,7 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
int count; int count;
try { try {
count = std::stoi(seedInput.substr(18), nullptr); count = std::stoi(seedInput.substr(18), nullptr);
} catch (std::invalid_argument& e) { count = 1; } catch (std::out_of_range& e) { } catch (std::invalid_argument&) { count = 1; } catch (std::out_of_range&) {
count = 1; count = 1;
} }
Playthrough::Playthrough_Repeat(excludedLocations, enabledTricks, count); Playthrough::Playthrough_Repeat(excludedLocations, enabledTricks, count);

View file

@ -14,8 +14,7 @@ void Random_Init(uint32_t seed) {
generator = boost::random::mt19937{ seed }; generator = boost::random::mt19937{ seed };
} }
// Returns a random integer in range [min, max-1] void Random_InitSeed() {
uint32_t Random(int min, int max) {
if (!init) { if (!init) {
// No seed given, get a random number from device to seed // No seed given, get a random number from device to seed
#if !defined(__SWITCH__) && !defined(__WIIU__) #if !defined(__SWITCH__) && !defined(__WIIU__)
@ -25,11 +24,16 @@ uint32_t Random(int min, int max) {
#endif #endif
Random_Init(seed); Random_Init(seed);
} }
}
// Returns a random unsigned integer in range [min, max-1]
uint32_t Random(uint32_t min, uint32_t max) {
Random_InitSeed();
boost::random::uniform_int_distribution<uint32_t> distribution(min, max - 1); boost::random::uniform_int_distribution<uint32_t> distribution(min, max - 1);
return distribution(generator); return distribution(generator);
} }
// Returns a random floating point number in [0.0, 1.0] // Returns a random floating point number in [0.0, 1.0)
double RandomDouble() { double RandomDouble() {
boost::random::uniform_real_distribution<double> distribution(0.0, 1.0); boost::random::uniform_real_distribution<double> distribution(0.0, 1.0);
return distribution(generator); return distribution(generator);

View file

@ -8,12 +8,12 @@
#include <set> #include <set>
void Random_Init(uint32_t seed); void Random_Init(uint32_t seed);
uint32_t Random(int min, int max); uint32_t Random(uint32_t min, uint32_t max);
double RandomDouble(); double RandomDouble();
// Get a random element from a vector or array // Get a random element from a vector or array
template <typename T> T RandomElement(std::vector<T>& vector, bool erase) { template <typename T> T RandomElement(std::vector<T>& vector, bool erase) {
const auto idx = Random(0, vector.size()); const auto idx = Random(0, static_cast<uint32_t>(vector.size()));
const T selected = vector[idx]; const T selected = vector[idx];
if (erase) { if (erase) {
vector.erase(vector.begin() + idx); vector.erase(vector.begin() + idx);
@ -21,17 +21,17 @@ template <typename T> T RandomElement(std::vector<T>& vector, bool erase) {
return selected; return selected;
} }
template <typename Container> auto& RandomElement(Container& container) { template <typename Container> auto& RandomElement(Container& container) {
return container[Random(0, std::size(container))]; return container[Random(0, static_cast<uint32_t>(std::size(container)))];
} }
template <typename Container> const auto& RandomElement(const Container& container) { template <typename Container> const auto& RandomElement(const Container& container) {
return container[Random(0, std::size(container))]; return container[Random(0, static_cast<uint32_t>(std::size(container)))];
} }
template <typename T> const T RandomElementFromSet(const std::set<T>& set) { template <typename T> const T RandomElementFromSet(const std::set<T>& set) {
if (set.size() == 1) { if (set.size() == 1) {
return *set.begin(); return *set.begin();
} }
uint32_t rand = Random(0, set.size()); uint32_t rand = Random(0, static_cast<uint32_t>(set.size()));
auto it = set.begin(); auto it = set.begin();
for (uint32_t i = 0; i < rand; i++) { for (uint32_t i = 0; i < rand; i++) {
it++; it++;
@ -43,12 +43,12 @@ template <typename T> const T RandomElementFromSet(const std::set<T>& set) {
// Shuffle items within a vector or array // Shuffle items within a vector or array
// RANDOTODO There's probably a more efficient way to do what this does. // RANDOTODO There's probably a more efficient way to do what this does.
template <typename T> void Shuffle(std::vector<T>& vector) { template <typename T> void Shuffle(std::vector<T>& vector) {
for (std::size_t i = 0; i + 1 < vector.size(); i++) { for (size_t i = 0; i + 1 < vector.size(); i++) {
std::swap(vector[i], vector[Random(i, vector.size())]); std::swap(vector[i], vector[Random(static_cast<uint32_t>(i), static_cast<uint32_t>(vector.size()))]);
} }
} }
template <typename T, std::size_t size> void Shuffle(std::array<T, size>& arr) { template <typename T, size_t size> void Shuffle(std::array<T, size>& arr) {
for (std::size_t i = 0; i + 1 < arr.size(); i++) { for (size_t i = 0; i + 1 < arr.size(); i++) {
std::swap(arr[i], arr[Random(i, arr.size())]); std::swap(arr[i], arr[Random(static_cast<uint32_t>(i), static_cast<uint32_t>(arr.size()))]);
} }
} }

View file

@ -115,7 +115,7 @@ uint16_t GetPriceFromSettings(Rando::Location* loc, PriceSettingsStruct priceSet
if (random < ShopPriceProbability[i]) { if (random < ShopPriceProbability[i]) {
// The randomly generated value has surpassed the total probability up to this point, so this is the // 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 // generated price i in range [0, 59], output in range [0, 295] in increments of 5
return i * 5; return static_cast<uint16_t>(i) * 5;
} }
} }
return 150; return 150;
@ -196,7 +196,8 @@ uint16_t GetCheapBalancedPrice() {
double random = RandomDouble(); double random = RandomDouble();
for (size_t i = 0; i < CheapPriceProbability.size(); i++) { for (size_t i = 0; i < CheapPriceProbability.size(); i++) {
if (random < CheapPriceProbability[i]) { if (random < CheapPriceProbability[i]) {
return i * 5; // i in range [0, 19], output in range [0, 95] in increments of 5 // i in range [0, 19], output in range [0, 95] in increments of 5
return static_cast<uint16_t>(i) * 5;
} }
} }
return -1; return -1;

View file

@ -633,7 +633,7 @@ void PlandomizerLoadSpoilerLog(std::string logFile) {
PlandomizerAddToItemList(plandomizerRandoRetrieveItem(RG_SOLD_OUT)); PlandomizerAddToItemList(plandomizerRandoRetrieveItem(RG_SOLD_OUT));
} }
} }
} catch (nlohmann::json::parse_error& e) { } catch (nlohmann::json::parse_error&) {
Notification::Emit({ .message = "Invalid Spoiler Log Format", .remainingTime = 10.0f }); Notification::Emit({ .message = "Invalid Spoiler Log Format", .remainingTime = 10.0f });
} }
} }
@ -967,7 +967,7 @@ void PlandomizerDrawOptions() {
} }
ImGui::TableNextColumn(); ImGui::TableNextColumn();
size_t index = 0; int32_t index = 0;
PlandoPushImageButtonStyle(); PlandoPushImageButtonStyle();
for (auto& hash : plandoHash) { for (auto& hash : plandoHash) {
ImGui::PushID(index); ImGui::PushID(index);
@ -995,7 +995,7 @@ void PlandomizerDrawOptions() {
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (downRet) { if (downRet) {
if (hash == 0) { if (hash == 0) {
hash = gSeedTextures.size() - 1; hash = static_cast<int32_t>(gSeedTextures.size()) - 1;
} else { } else {
hash--; hash--;
} }

View file

@ -19,7 +19,7 @@ void EnCow_MoveForRandomizer(EnCow* enCow, PlayState* play) {
// Move left cow in lon lon tower // Move left cow in lon lon tower
enCow->actor.world.pos.x = -229.0f; enCow->actor.world.pos.x = -229.0f;
enCow->actor.world.pos.z = 157.0f; enCow->actor.world.pos.z = 157.0f;
enCow->actor.shape.rot.y = 15783.0f; enCow->actor.shape.rot.y = 15783;
moved = true; moved = true;
} else if (play->sceneNum == SCENE_STABLE && enCow->actor.world.pos.x == -3 && enCow->actor.world.pos.z == -254) { } else if (play->sceneNum == SCENE_STABLE && enCow->actor.world.pos.x == -3 && enCow->actor.world.pos.z == -254) {
// Move right cow in lon lon stable // Move right cow in lon lon stable
@ -39,7 +39,8 @@ void RegisterShuffleCows() {
COND_VB_SHOULD(VB_GIVE_ITEM_FROM_COW, shouldRegister, { COND_VB_SHOULD(VB_GIVE_ITEM_FROM_COW, shouldRegister, {
EnCow* enCow = va_arg(args, EnCow*); EnCow* enCow = va_arg(args, EnCow*);
CowIdentity cowIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCow( CowIdentity cowIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCow(
gPlayState->sceneNum, enCow->actor.world.pos.x, enCow->actor.world.pos.z); gPlayState->sceneNum, static_cast<int32_t>(enCow->actor.world.pos.x),
static_cast<int32_t>(enCow->actor.world.pos.z));
// Has this cow already rewarded an item? // Has this cow already rewarded an item?
if (!Flags_GetRandomizerInf(cowIdentity.randomizerInf)) { if (!Flags_GetRandomizerInf(cowIdentity.randomizerInf)) {
Flags_SetRandomizerInf(cowIdentity.randomizerInf); Flags_SetRandomizerInf(cowIdentity.randomizerInf);

View file

@ -3,6 +3,7 @@
#include "static_data.h" #include "static_data.h"
#include <libultraship/libultra.h> #include <libultraship/libultra.h>
#include "global.h" #include "global.h"
#include "soh/ResourceManagerHelpers.h"
extern "C" { extern "C" {
#include "variables.h" #include "variables.h"
@ -11,7 +12,6 @@ extern "C" {
#include "overlays/actors/ovl_Obj_Kibako/z_obj_kibako.h" #include "overlays/actors/ovl_Obj_Kibako/z_obj_kibako.h"
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" #include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
#include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/enhancementTypes.h"
#include "soh/ResourceManagerHelpers.h"
extern PlayState* gPlayState; extern PlayState* gPlayState;
} }
@ -195,7 +195,7 @@ void ObjKibako2_RandomizerSpawnCollectible(ObjKibako2* crateActor, PlayState* pl
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f; item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f; item00->actor.speedXZ = 2.0f;
item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f); item00->actor.world.rot.y = static_cast<int16_t>(Rand_CenteredFloat(65536.0f));
} }
void ObjKibako_RandomizerSpawnCollectible(ObjKibako* smallCrateActor, PlayState* play) { void ObjKibako_RandomizerSpawnCollectible(ObjKibako* smallCrateActor, PlayState* play) {
@ -206,7 +206,7 @@ void ObjKibako_RandomizerSpawnCollectible(ObjKibako* smallCrateActor, PlayState*
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f; item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f; item00->actor.speedXZ = 2.0f;
item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f); item00->actor.world.rot.y = static_cast<int16_t>(Rand_CenteredFloat(65536.0f));
} }
void ObjKibako2_RandomizerInit(void* actorRef) { void ObjKibako2_RandomizerInit(void* actorRef) {

View file

@ -117,7 +117,7 @@ void EnKusa_RandomizerSpawnCollectible(EnKusa* grassActor, PlayState* play) {
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f; item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f; item00->actor.speedXZ = 2.0f;
item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f); item00->actor.world.rot.y = static_cast<int16_t>(Rand_CenteredFloat(65536.0f));
} }
void EnKusa_RandomizerInit(void* actorRef) { void EnKusa_RandomizerInit(void* actorRef) {

View file

@ -48,7 +48,7 @@ void ObjTsubo_RandomizerSpawnCollectible(ObjTsubo* potActor, PlayState* play) {
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f; item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f; item00->actor.speedXZ = 2.0f;
item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f); item00->actor.world.rot.y = static_cast<int16_t>(Rand_CenteredFloat(65536.0f));
} }
void ObjTsubo_RandomizerInit(void* actorRef) { void ObjTsubo_RandomizerInit(void* actorRef) {

View file

@ -597,7 +597,7 @@ extern "C" s32 OverrideLimbDrawBarinade(PlayState* play, s32 limbIndex, Gfx** dL
(uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 8, 16, 1, 0, (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 8, 16, 1, 0,
(play->gameplayFrames * -2) % 64, 16, 16)); (play->gameplayFrames * -2) % 64, 16, 16));
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 200); gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 200);
Matrix_RotateX(-M_PI / 2, MTXMODE_APPLY); Matrix_RotateX(-M_PIf / 2.0f, MTXMODE_APPLY);
} else if ((limbIndex >= 10) && (limbIndex < 20)) { } else if ((limbIndex >= 10) && (limbIndex < 20)) {
rot->x -= 0x4000; rot->x -= 0x4000;
*dList = NULL; *dList = NULL;
@ -1097,7 +1097,7 @@ extern "C" void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getIte
gSPSegment(POLY_XLU_DISP++, 0x08, gSPSegment(POLY_XLU_DISP++, 0x08,
(uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 1 * (play->state.frames * 2), (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 1 * (play->state.frames * 2),
-1 * (play->state.frames * 2), 64, 64, 1, 1 * (play->state.frames * 4), -1 * (play->state.frames * 2), 64, 64, 1, 1 * (play->state.frames * 4),
1 * -(play->state.frames * 4), 32, 32)); -1 * (play->state.frames * 4), 32, 32));
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD); G_MTX_MODELVIEW | G_MTX_LOAD);
@ -1116,7 +1116,7 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI
// Draw rod // Draw rod
Gfx_SetupDL_25Opa(play->state.gfxCtx); Gfx_SetupDL_25Opa(play->state.gfxCtx);
Matrix_Scale(0.2, 0.2, 0.2, MTXMODE_APPLY); Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD); G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingPoleGiDL); gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingPoleGiDL);
@ -1126,8 +1126,8 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI
Matrix_Scale(5.0f, 5.0f, 5.0f, MTXMODE_APPLY); Matrix_Scale(5.0f, 5.0f, 5.0f, MTXMODE_APPLY);
pos = { 0.0f, -25.5f, -4.0f }; pos = { 0.0f, -25.5f, -4.0f };
Matrix_Translate(pos.x, pos.y, pos.z, MTXMODE_APPLY); Matrix_Translate(pos.x, pos.y, pos.z, MTXMODE_APPLY);
Matrix_RotateZ(-M_PI_2, MTXMODE_APPLY); Matrix_RotateZ(-M_PI_2f, MTXMODE_APPLY);
Matrix_RotateY(-M_PI_2 - 0.2f, MTXMODE_APPLY); Matrix_RotateY(-M_PI_2f - 0.2f, MTXMODE_APPLY);
Matrix_Scale(0.006f, 0.006f, 0.006f, MTXMODE_APPLY); Matrix_Scale(0.006f, 0.006f, 0.006f, MTXMODE_APPLY);
Gfx_SetupDL_25Opa(play->state.gfxCtx); Gfx_SetupDL_25Opa(play->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
@ -1140,7 +1140,7 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL); gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
Matrix_RotateZ(M_PI_2, MTXMODE_APPLY); Matrix_RotateZ(M_PI_2f, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL); gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
@ -1149,7 +1149,7 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL); gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
Matrix_RotateZ(M_PI / 2, MTXMODE_APPLY); Matrix_RotateZ(M_PIf / 2.0f, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL); gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);

View file

@ -1645,7 +1645,7 @@ void EntranceShuffler::ParseJson(nlohmann::json spoilerFileJson) {
try { try {
nlohmann::json entrancesJson = spoilerFileJson["entrances"]; nlohmann::json entrancesJson = spoilerFileJson["entrances"];
size_t i = 0; size_t i = 0;
for (auto it = entrancesJson.begin(); it != entrancesJson.end(); ++it, i++) { for (auto it = entrancesJson.begin(); it != entrancesJson.end() && i < entranceOverrides.size(); ++it, i++) {
nlohmann::json entranceJson = *it; nlohmann::json entranceJson = *it;
for (auto entranceIt = entranceJson.begin(); entranceIt != entranceJson.end(); ++entranceIt) { for (auto entranceIt = entranceJson.begin(); entranceIt != entranceJson.end(); ++entranceIt) {
if (entranceIt.key() == "type") { if (entranceIt.key() == "type") {

View file

@ -90,7 +90,7 @@ class Entrance {
Entrance* reverse = nullptr; Entrance* reverse = nullptr;
Entrance* assumed = nullptr; Entrance* assumed = nullptr;
Entrance* replacement = nullptr; Entrance* replacement = nullptr;
int16_t index = 0xFFFF; int16_t index = -1;
bool shuffled = false; bool shuffled = false;
bool primary = false; bool primary = false;
bool addedToPool = false; bool addedToPool = false;

View file

@ -136,8 +136,9 @@ Fishsanity::GetFishingPondLocations(FishsanityOptionsSource optionsSource) {
} }
// NOTE: This only works because we can assume activeFish is already sorted; changes that break this assumption will // NOTE: This only works because we can assume activeFish is already sorted; changes that break this assumption will
// also break this // also break this
FilterAndEraseFromPool(remainingFish, FilterAndEraseFromPool(remainingFish, [&](RandomizerCheck loc) {
[&](uint32_t loc) { return std::binary_search(activeFish.begin(), activeFish.end(), loc); }); return std::binary_search(activeFish.begin(), activeFish.end(), loc);
});
return std::make_pair(activeFish, remainingFish); return std::make_pair(activeFish, remainingFish);
} }

View file

@ -226,7 +226,8 @@ uint8_t Hint::GetNumberOfMessages() const {
if (numMessages == 0) { if (numMessages == 0) {
numMessages = 1; // RANDOTODO make std::max actually fucking work for 3 arguments numMessages = 1; // RANDOTODO make std::max actually fucking work for 3 arguments
} }
return numMessages; // RANDOTODO will number of messages always be u8?
return static_cast<uint8_t>(numMessages);
} }
const std::vector<std::string> Hint::GetAllMessageStrings(MessageFormat format) const { const std::vector<std::string> Hint::GetAllMessageStrings(MessageFormat format) const {

View file

@ -328,7 +328,7 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() {
(getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK || (getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK ||
getItemEntry.getItemCategory == ITEM_CATEGORY_SKULL_TOKEN || getItemEntry.getItemCategory == ITEM_CATEGORY_SKULL_TOKEN ||
getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER))))) { getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER))))) {
Item_DropCollectible(gPlayState, &spawnPos, ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000); Item_DropCollectible(gPlayState, &spawnPos, static_cast<int16_t>(ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000));
} }
} }
@ -1013,7 +1013,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
if (item00->itemEntry.getItemId == GI_SWORD_BGS) { if (item00->itemEntry.getItemId == GI_SWORD_BGS) {
gSaveContext.bgsFlag = true; gSaveContext.bgsFlag = true;
} }
Item_Give(gPlayState, item00->itemEntry.itemId); Item_Give(gPlayState, static_cast<uint8_t>(item00->itemEntry.itemId));
} else if (item00->itemEntry.modIndex == MOD_RANDOMIZER) { } else if (item00->itemEntry.modIndex == MOD_RANDOMIZER) {
if (item00->itemEntry.getItemId == RG_ICE_TRAP) { if (item00->itemEntry.getItemId == RG_ICE_TRAP) {
gSaveContext.ship.pendingIceTrapCount++; gSaveContext.ship.pendingIceTrapCount++;
@ -2137,27 +2137,27 @@ void RandomizerOnActorInitHandler(void* actorRef) {
void RandomizerOnGameFrameUpdateHandler() { void RandomizerOnGameFrameUpdateHandler() {
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER)) { if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER)) {
AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER); AMMO(ITEM_BOW) = static_cast<int8_t>(CUR_CAPACITY(UPG_QUIVER));
} }
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG)) { if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG)) {
AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG); AMMO(ITEM_BOMB) = static_cast<int8_t>(CUR_CAPACITY(UPG_BOMB_BAG));
} }
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG)) { if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG)) {
AMMO(ITEM_SLINGSHOT) = CUR_CAPACITY(UPG_BULLET_BAG); AMMO(ITEM_SLINGSHOT) = static_cast<int8_t>(CUR_CAPACITY(UPG_BULLET_BAG));
} }
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE)) { if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE)) {
AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); AMMO(ITEM_STICK) = static_cast<int8_t>(CUR_CAPACITY(UPG_STICKS));
} }
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE)) { if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE)) {
AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS); AMMO(ITEM_NUT) = static_cast<int8_t>(CUR_CAPACITY(UPG_NUTS));
} }
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) { if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) {
gSaveContext.magic = gSaveContext.magicCapacity; gSaveContext.magic = static_cast<int8_t>(gSaveContext.magicCapacity);
} }
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS)) { if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS)) {
@ -2165,7 +2165,7 @@ void RandomizerOnGameFrameUpdateHandler() {
} }
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MONEY)) { if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MONEY)) {
gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET); gSaveContext.rupees = static_cast<int8_t>(CUR_CAPACITY(UPG_WALLET));
} }
if (!Flags_GetRandomizerInf(RAND_INF_HAS_WALLET)) { if (!Flags_GetRandomizerInf(RAND_INF_HAS_WALLET)) {
@ -2203,7 +2203,8 @@ void RandomizerOnActorUpdateHandler(void* refActor) {
if (actor->id == ACTOR_OBJ_COMB) { if (actor->id == ACTOR_OBJ_COMB) {
ObjComb* combActor = reinterpret_cast<ObjComb*>(actor); ObjComb* combActor = reinterpret_cast<ObjComb*>(actor);
combActor->actor.shape.rot.x = combActor->actor.shape.rot.x =
Math_SinS(combActor->unk_1B2) * CLAMP_MIN(combActor->unk_1B0, 0) + combActor->actor.home.rot.x; static_cast<int16_t>(Math_SinS(combActor->unk_1B2)) * CLAMP_MIN(combActor->unk_1B0, 0) +
combActor->actor.home.rot.x;
} }
} }
@ -2216,29 +2217,29 @@ typedef struct {
// special respawns used when voided out without swim to prevent infinite loops // special respawns used when voided out without swim to prevent infinite loops
std::map<s32, SpecialRespawnInfo> swimSpecialRespawnInfo = { std::map<s32, SpecialRespawnInfo> swimSpecialRespawnInfo = {
{ ENTR_ZORAS_RIVER_3, // hf to zr in water { ENTR_ZORAS_RIVER_3, // hf to zr in water
{ { -1455.443, -20, 1384.826 }, 28761 } }, { { -1455.443f, -20.0f, 1384.826f }, 28761 } },
{ ENTR_HYRULE_FIELD_14, // zr to hf in water { ENTR_HYRULE_FIELD_14, // zr to hf in water
{ { 5730.209, -20, 3725.911 }, -20025 } }, { { 5730.209f, -20.0f, 3725.911f }, -20025 } },
{ ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, // zr to lw { ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, // zr to lw
{ { 1978.718, -36.908, -855 }, -16384 } }, { { 1978.718f, -36.908f, -855.0f }, -16384 } },
{ ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, // lw to zr { ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, // lw to zr
{ { 4082.366, 860.442, -1018.949 }, -32768 } }, { { 4082.366f, 860.442f, -1018.949f }, -32768 } },
{ ENTR_LAKE_HYLIA_RIVER_EXIT, // gv to lh { ENTR_LAKE_HYLIA_RIVER_EXIT, // gv to lh
{ { -3276.416, -1033, 2908.421 }, 11228 } }, { { -3276.416f, -1033.0f, 2908.421f }, 11228 } },
{ ENTR_WATER_TEMPLE_ENTRANCE, // lh to water temple { ENTR_WATER_TEMPLE_ENTRANCE, // lh to water temple
{ { -182, 780, 759.5 }, -32768 } }, { { -182.0f, 780.0f, 759.5f }, -32768 } },
{ ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, // water temple to lh { ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, // water temple to lh
{ { -955.028, -1306.9, 6768.954 }, -32768 } }, { { -955.028f, -1306.9f, 6768.954f }, -32768 } },
{ ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, // lh to zd { ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, // lh to zd
{ { -109.86, 11.396, -9.933 }, -29131 } }, { { -109.86f, 11.396f, -9.933f }, -29131 } },
{ ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, // zd to lh { ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, // zd to lh
{ { -912, -1326.967, 3391 }, 0 } }, { { -912.0f, -1326.967f, 3391.0f }, 0 } },
{ ENTR_GERUDO_VALLEY_1, // caught by gerudos as child { ENTR_GERUDO_VALLEY_1, // caught by gerudos as child
{ { -424, -2051, -74 }, 16384 } }, { { -424.0f, -2051.0f, -74.0f }, 16384 } },
{ ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, // mk to hf (can be a problem when it then turns night) { ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, // mk to hf (can be a problem when it then turns night)
{ { 0, 0, 1100 }, 0 } }, { { 0.0f, 0.0f, 1100.0f }, 0 } },
{ ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP, // jabu blue warp to zf { ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP, // jabu blue warp to zf
{ { -1580, 150, 1670 }, 8000 } }, { { -1580.0f, 150.0f, 1670.0f }, 8000 } },
}; };
f32 triforcePieceScale; f32 triforcePieceScale;
@ -2298,8 +2299,8 @@ void RandomizerOnSceneSpawnActorsHandler() {
switch (gPlayState->sceneNum) { switch (gPlayState->sceneNum) {
case SCENE_TEMPLE_OF_TIME: case SCENE_TEMPLE_OF_TIME:
if (gPlayState->roomCtx.curRoom.num == 1) { if (gPlayState->roomCtx.curRoom.num == 1) {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_XC, -104, -40, 2382, 0, 0x8000, 0, Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_XC, -104, -40, 2382, 0,
SHEIK_TYPE_RANDO, false); static_cast<int16_t>(0x8000), 0, SHEIK_TYPE_RANDO, false);
} }
break; break;
case SCENE_INSIDE_GANONS_CASTLE: case SCENE_INSIDE_GANONS_CASTLE:

View file

@ -10,9 +10,10 @@
#include "soh/Enhancements/debugger/performanceTimer.h" #include "soh/Enhancements/debugger/performanceTimer.h"
#include <fstream> #include <fstream>
#include <soh/OTRGlobals.h>
#include "3drando/shops.hpp"
extern "C" { extern "C" {
extern SaveContext gSaveContext;
extern PlayState* gPlayState; extern PlayState* gPlayState;
} }
@ -45,17 +46,71 @@ bool LocationAccess::ConditionsMet(Region* parentRegion, bool calculatingAvailab
conditionsMet = true; conditionsMet = true;
} }
return conditionsMet && return conditionsMet && CanBuy(calculatingAvailableChecks);
(calculatingAvailableChecks || CanBuy()); // TODO: run CanBuy when price is known due to settings
} }
bool LocationAccess::CanBuy() const { static uint16_t GetMinimumPrice(const Rando::Location* loc) {
return CanBuyAnother(location); extern PriceSettingsStruct shopsanityPrices;
extern PriceSettingsStruct scrubPrices;
extern PriceSettingsStruct merchantPrices;
PriceSettingsStruct priceSettings = loc->GetRCType() == RCTYPE_SHOP ? shopsanityPrices
: loc->GetRCType() == RCTYPE_SCRUB ? scrubPrices
: merchantPrices;
auto ctx = Rando::Context::GetInstance();
switch (ctx->GetOption(priceSettings.main).Get()) {
case RO_PRICE_VANILLA:
return loc->GetVanillaPrice();
case RO_PRICE_CHEAP_BALANCED:
return 0;
case RO_PRICE_BALANCED:
return 0;
case RO_PRICE_FIXED:
return ctx->GetOption(priceSettings.fixedPrice).Get() * 5;
case RO_PRICE_RANGE: {
uint16_t range1 = ctx->GetOption(priceSettings.range1).Get() * 5;
uint16_t range2 = ctx->GetOption(priceSettings.range1).Get() * 5;
return range1 < range2 ? range1 : range2;
}
case RO_PRICE_SET_BY_WALLET: {
if (ctx->GetOption(priceSettings.noWallet).Get()) {
return 0;
} else if (ctx->GetOption(priceSettings.childWallet).Get()) {
return 1;
} else if (ctx->GetOption(priceSettings.adultWallet).Get()) {
return 100;
} else if (ctx->GetOption(priceSettings.giantWallet).Get()) {
return 201;
} else {
return 501;
}
}
default:
return 0;
}
}
bool LocationAccess::CanBuy(bool calculatingAvailableChecks) const {
const auto& loc = Rando::StaticData::GetLocation(location);
const auto& itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(location);
if (loc->GetRCType() == RCTYPE_SHOP || loc->GetRCType() == RCTYPE_SCRUB || loc->GetRCType() == RCTYPE_MERCHANT) {
// Checks should only be identified while playing
if (calculatingAvailableChecks && itemLoc->GetCheckStatus() != RCSHOW_IDENTIFIED) {
return CanBuyAnother(GetMinimumPrice(loc));
} else {
return CanBuyAnother(itemLoc->GetPrice());
}
}
return true;
} }
bool CanBuyAnother(RandomizerCheck rc) { bool CanBuyAnother(RandomizerCheck rc) {
uint16_t price = ctx->GetItemLocation(rc)->GetPrice(); return CanBuyAnother(ctx->GetItemLocation(rc)->GetPrice());
}
bool CanBuyAnother(uint16_t price) {
if (price > 500) { if (price > 500) {
return logic->HasItem(RG_TYCOON_WALLET); return logic->HasItem(RG_TYCOON_WALLET);
} else if (price > 200) { } else if (price > 200) {
@ -275,7 +330,7 @@ bool BeanPlanted(const RandomizerRegion region) {
if (gPlayState != nullptr && gPlayState->sceneNum == sceneID) { if (gPlayState != nullptr && gPlayState->sceneNum == sceneID) {
swch = gPlayState->actorCtx.flags.swch; swch = gPlayState->actorCtx.flags.swch;
} else if (sceneID != SCENE_ID_MAX) { } else if (sceneID != SCENE_ID_MAX) {
swch = gSaveContext.sceneFlags[sceneID].swch; swch = Rando::Context::GetInstance()->GetLogic()->GetSaveContext()->sceneFlags[sceneID].swch;
} else { } else {
swch = 0; swch = 0;
} }
@ -312,7 +367,7 @@ void RegionTable_Init() {
logic = ctx->GetLogic(); // RANDOTODO do not hardcode, instead allow accepting a Logic class somehow logic = ctx->GetLogic(); // RANDOTODO do not hardcode, instead allow accepting a Logic class somehow
grottoEvents = { grottoEvents = {
EventAccess(&logic->GossipStoneFairy, [] { return logic->CallGossipFairy(); }), EventAccess(&logic->GossipStoneFairy, [] { return logic->CallGossipFairy(); }),
EventAccess(&logic->ButterflyFairy, [] { return logic->ButterflyFairy || (logic->CanUse(RG_STICKS)); }), EventAccess(&logic->ButterflyFairy, [] { return logic->CanUse(RG_STICKS); }),
EventAccess(&logic->BugShrub, [] { return logic->CanCutShrubs(); }), EventAccess(&logic->BugShrub, [] { return logic->CanCutShrubs(); }),
EventAccess(&logic->LoneFish, [] { return true; }), EventAccess(&logic->LoneFish, [] { return true; }),
}; };
@ -480,17 +535,17 @@ std::string CleanCheckConditionString(std::string condition) {
} }
namespace Regions { namespace Regions {
const auto GetAllRegions() { auto GetAllRegions() {
static const size_t regionCount = RR_MAX - (RR_NONE + 1); static const size_t regionCount = RR_MAX - (RR_NONE + 1);
static std::array<RandomizerRegion, regionCount> allRegions = {}; static std::array<RandomizerRegion, regionCount> allRegions = {};
static bool intialized = false; static bool initialized = false;
if (!intialized) { if (!initialized) {
for (size_t i = 0; i < regionCount; i++) { for (size_t i = 0; i < regionCount; i++) {
allRegions[i] = (RandomizerRegion)((RR_NONE + 1) + i); allRegions[i] = (RandomizerRegion)((RR_NONE + 1) + i);
} }
intialized = true; initialized = true;
} }
return allRegions; return allRegions;
@ -629,7 +684,7 @@ std::vector<Rando::Entrance*> GetShuffleableEntrances(Rando::EntranceType type,
Rando::Entrance* GetEntrance(RandomizerRegion source, RandomizerRegion destination) { Rando::Entrance* GetEntrance(RandomizerRegion source, RandomizerRegion destination) {
for (auto& exit : RegionTable(source)->exits) { for (auto& exit : RegionTable(source)->exits) {
if (exit.GetConnectedRegionKey() == destination) { if (exit.GetOriginalConnectedRegionKey() == destination) {
return &exit; return &exit;
} }
} }

View file

@ -100,9 +100,10 @@ class LocationAccess {
std::string condition_str; std::string condition_str;
// Makes sure shop locations are buyable // Makes sure shop locations are buyable
bool CanBuy() const; bool CanBuy(bool calculatingAvailableChecks) const;
}; };
bool CanBuyAnother(uint16_t price);
bool CanBuyAnother(RandomizerCheck rc); bool CanBuyAnother(RandomizerCheck rc);
namespace Rando { namespace Rando {

View file

@ -25,7 +25,6 @@ void RegionTable_Init_BottomOfTheWell() {
}, { }, {
//Locations //Locations
LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives()), LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives()),
LOCATION(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, (logic->HasItem(RG_BRONZE_SCALE) || logic->LoweredWaterInsideBotw) && logic->CanUse(RG_STICKS) || logic->CanUse(RG_DINS_FIRE)),
LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->LoweredWaterInsideBotw), LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->LoweredWaterInsideBotw),
LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->LoweredWaterInsideBotw), LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->LoweredWaterInsideBotw),
LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_1, logic->CanBreakPots()),

View file

@ -445,7 +445,7 @@ void RegionTable_Init_DekuTree() {
areaTable[RR_DEKU_TREE_BOSS_ROOM] = Region("Deku Tree Boss Room", "Deku Tree", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_DEKU_TREE_BOSS_ROOM] = Region("Deku Tree Boss Room", "Deku Tree", {}, NO_DAY_NIGHT_CYCLE, {
// Events // Events
EventAccess(&logic->DekuTreeClear, []{return logic->DekuTreeClear || logic->CanKillEnemy(RE_GOHMA);}), EventAccess(&logic->DekuTreeClear, []{return logic->CanKillEnemy(RE_GOHMA);}),
}, { }, {
// Locations // Locations
LOCATION(RC_QUEEN_GOHMA, logic->DekuTreeClear), LOCATION(RC_QUEEN_GOHMA, logic->DekuTreeClear),

View file

@ -567,7 +567,7 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_BOSS_ROOM] = Region("Dodongos Cavern Boss Room", "Dodongos Cavern", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_DODONGOS_CAVERN_BOSS_ROOM] = Region("Dodongos Cavern Boss Room", "Dodongos Cavern", {}, NO_DAY_NIGHT_CYCLE, {
// Events // Events
EventAccess(&logic->DodongosCavernClear, []{return logic->DodongosCavernClear || (Here(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return logic->HasExplosives() || (logic->CanUse(RG_MEGATON_HAMMER) && ctx->GetTrickOption(RT_DC_HAMMER_FLOOR));}) && logic->CanKillEnemy(RE_KING_DODONGO)); /*todo add chu kill to tricks*/}), EventAccess(&logic->DodongosCavernClear, []{return Here(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return logic->HasExplosives() || (logic->CanUse(RG_MEGATON_HAMMER) && ctx->GetTrickOption(RT_DC_HAMMER_FLOOR));}) && logic->CanKillEnemy(RE_KING_DODONGO); /*todo add chu kill to tricks*/}),
}, { }, {
// Locations // Locations
LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, true), LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, true),

View file

@ -20,14 +20,14 @@ void RegionTable_Init_FireTemple() {
//Exits //Exits
Entrance(RR_FIRE_TEMPLE_ENTRYWAY, []{return true;}), Entrance(RR_FIRE_TEMPLE_ENTRYWAY, []{return true;}),
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return logic->FireTimer() >= 24;}), Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return logic->FireTimer() >= 24;}),
Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return Here(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}) && (logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsKeysanity);}), Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return Here(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}) && (logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked);}),
Entrance(RR_FIRE_TEMPLE_LOOP_EXIT, []{return true;}), Entrance(RR_FIRE_TEMPLE_LOOP_EXIT, []{return true;}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 2) && logic->FireTimer() >= 24;}), Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 2) && logic->FireTimer() >= 24;}),
}); });
areaTable[RR_FIRE_TEMPLE_NEAR_BOSS_ROOM] = Region("Fire Temple Near Boss Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_FIRE_TEMPLE_NEAR_BOSS_ROOM] = Region("Fire Temple Near Boss Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->FairyPot, []{return logic->FairyPot || (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}), EventAccess(&logic->FairyPot, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}),
}, { }, {
//Locations //Locations
LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, true), LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, true),
@ -43,7 +43,7 @@ void RegionTable_Init_FireTemple() {
areaTable[RR_FIRE_TEMPLE_LOOP_ENEMIES] = Region("Fire Temple Loop Enemies", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { areaTable[RR_FIRE_TEMPLE_LOOP_ENEMIES] = Region("Fire Temple Loop Enemies", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits //Exits
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsKeysanity;}), Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked;}),
Entrance(RR_FIRE_TEMPLE_LOOP_TILES, []{return Here(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return logic->CanKillEnemy(RE_TORCH_SLUG) && logic->CanKillEnemy(RE_FIRE_KEESE);});}), Entrance(RR_FIRE_TEMPLE_LOOP_TILES, []{return Here(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return logic->CanKillEnemy(RE_TORCH_SLUG) && logic->CanKillEnemy(RE_FIRE_KEESE);});}),
}); });
@ -67,7 +67,7 @@ void RegionTable_Init_FireTemple() {
areaTable[RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH] = Region("Fire Temple Loop Hammer Switch", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH] = Region("Fire Temple Loop Hammer Switch", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->FireLoopSwitch, []{return logic->FireLoopSwitch || logic->CanUse(RG_MEGATON_HAMMER);}), EventAccess(&logic->FireLoopSwitch, []{return logic->CanUse(RG_MEGATON_HAMMER);}),
}, {}, { }, {}, {
//Exits //Exits
Entrance(RR_FIRE_TEMPLE_LOOP_FLARE_DANCER, []{return true;}), Entrance(RR_FIRE_TEMPLE_LOOP_FLARE_DANCER, []{return true;}),
@ -745,7 +745,7 @@ void RegionTable_Init_FireTemple() {
areaTable[RR_FIRE_TEMPLE_BOSS_ROOM] = Region("Fire Temple Boss Room", "Fire Temple", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_FIRE_TEMPLE_BOSS_ROOM] = Region("Fire Temple Boss Room", "Fire Temple", {}, NO_DAY_NIGHT_CYCLE, {
// Events // Events
EventAccess(&logic->FireTempleClear, []{return logic->FireTempleClear || (logic->FireTimer() >= 64 && logic->CanKillEnemy(RE_VOLVAGIA));}), EventAccess(&logic->FireTempleClear, []{return logic->FireTimer() >= 64 && logic->CanKillEnemy(RE_VOLVAGIA);}),
}, { }, {
// Locations // Locations
LOCATION(RC_FIRE_TEMPLE_VOLVAGIA_HEART, logic->FireTempleClear), LOCATION(RC_FIRE_TEMPLE_VOLVAGIA_HEART, logic->FireTempleClear),

View file

@ -34,7 +34,7 @@ void RegionTable_Init_ForestTemple() {
areaTable[RR_FOREST_TEMPLE_LOBBY] = Region("Forest Temple Lobby", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_FOREST_TEMPLE_LOBBY] = Region("Forest Temple Lobby", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->ForestTempleMeg, []{return logic->ForestTempleMeg || (logic->ForestTempleJoelle && logic->ForestTempleBeth && logic->ForestTempleAmy && logic->CanUse(RG_FAIRY_BOW));}), EventAccess(&logic->ForestTempleMeg, []{return logic->ForestTempleJoelle && logic->ForestTempleBeth && logic->ForestTempleAmy && logic->CanUse(RG_FAIRY_BOW);}),
}, { }, {
//Locations //Locations
LOCATION(RC_FOREST_TEMPLE_GS_LOBBY, logic->HookshotOrBoomerang()), LOCATION(RC_FOREST_TEMPLE_GS_LOBBY, logic->HookshotOrBoomerang()),
@ -203,7 +203,7 @@ void RegionTable_Init_ForestTemple() {
areaTable[RR_FOREST_TEMPLE_RED_POE_ROOM] = Region("Forest Temple Red Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_FOREST_TEMPLE_RED_POE_ROOM] = Region("Forest Temple Red Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->ForestTempleJoelle, []{return logic->ForestTempleJoelle || logic->CanUse(RG_FAIRY_BOW);}), EventAccess(&logic->ForestTempleJoelle, []{return logic->CanUse(RG_FAIRY_BOW);}),
}, { }, {
//Locations //Locations
LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->ForestTempleJoelle), LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->ForestTempleJoelle),
@ -228,7 +228,7 @@ void RegionTable_Init_ForestTemple() {
areaTable[RR_FOREST_TEMPLE_BLUE_POE_ROOM] = Region("Forest Temple Blue Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_FOREST_TEMPLE_BLUE_POE_ROOM] = Region("Forest Temple Blue Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->ForestTempleBeth, []{return logic->ForestTempleBeth || logic->CanUse(RG_FAIRY_BOW);}), EventAccess(&logic->ForestTempleBeth, []{return logic->CanUse(RG_FAIRY_BOW);}),
}, { }, {
//Locations //Locations
LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->ForestTempleBeth), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->ForestTempleBeth),
@ -274,7 +274,7 @@ void RegionTable_Init_ForestTemple() {
areaTable[RR_FOREST_TEMPLE_GREEN_POE_ROOM] = Region("Forest Temple Green Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_FOREST_TEMPLE_GREEN_POE_ROOM] = Region("Forest Temple Green Poe Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->ForestTempleAmy, []{return logic->ForestTempleAmy || logic->CanUse(RG_FAIRY_BOW);}), EventAccess(&logic->ForestTempleAmy, []{return logic->CanUse(RG_FAIRY_BOW);}),
}, { }, {
//Locations //Locations
LOCATION(RC_FOREST_TEMPLE_GREEN_POE_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_GREEN_POE_POT_1, logic->CanBreakPots()),
@ -608,7 +608,7 @@ void RegionTable_Init_ForestTemple() {
areaTable[RR_FOREST_TEMPLE_BOSS_ROOM] = Region("Forest Temple Boss Room", "Forest Temple", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_FOREST_TEMPLE_BOSS_ROOM] = Region("Forest Temple Boss Room", "Forest Temple", {}, NO_DAY_NIGHT_CYCLE, {
// Events // Events
EventAccess(&logic->ForestTempleClear, []{return logic->ForestTempleClear || logic->CanKillEnemy(RE_PHANTOM_GANON);}), EventAccess(&logic->ForestTempleClear, []{return logic->CanKillEnemy(RE_PHANTOM_GANON);}),
}, { }, {
// Locations // Locations
LOCATION(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, logic->ForestTempleClear), LOCATION(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, logic->ForestTempleClear),

View file

@ -80,7 +80,7 @@ void RegionTable_Init_GanonsCastle() {
areaTable[RR_GANONS_CASTLE_WATER_TRIAL] = Region("Ganon's Castle Water Trial", "Ganon's Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_GANONS_CASTLE_WATER_TRIAL] = Region("Ganon's Castle Water Trial", "Ganon's Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->BlueFireAccess, []{return true;}), EventAccess(&logic->BlueFireAccess, []{return true;}),
EventAccess(&logic->FairyPot, []{return logic->FairyPot || (logic->BlueFire() && logic->CanKillEnemy(RE_FREEZARD));}), EventAccess(&logic->FairyPot, []{return logic->BlueFire() && logic->CanKillEnemy(RE_FREEZARD);}),
EventAccess(&logic->WaterTrialClear, []{return logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_LIGHT_ARROWS);}), EventAccess(&logic->WaterTrialClear, []{return logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_LIGHT_ARROWS);}),
}, { }, {
//Locations //Locations
@ -109,7 +109,7 @@ void RegionTable_Init_GanonsCastle() {
areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL] = Region("Ganon's Castle Spirit Trial", "Ganon's Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL] = Region("Ganon's Castle Spirit Trial", "Ganon's Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->NutPot, []{return logic->NutPot || (((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))));}), EventAccess(&logic->NutPot, []{return ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)));}),
EventAccess(&logic->SpiritTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_MIRROR_SHIELD) || ctx->GetOption(RSK_SUNLIGHT_ARROWS)) && logic->CanUse(RG_BOMBCHU_5) && ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT));}), EventAccess(&logic->SpiritTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_MIRROR_SHIELD) || ctx->GetOption(RSK_SUNLIGHT_ARROWS)) && logic->CanUse(RG_BOMBCHU_5) && ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT));}),
}, { }, {
//Locations //Locations

View file

@ -361,7 +361,7 @@ void RegionTable_Init_JabuJabusBelly() {
areaTable[RR_JABU_JABUS_BELLY_BOSS_ROOM] = Region("Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_JABU_JABUS_BELLY_BOSS_ROOM] = Region("Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", {}, NO_DAY_NIGHT_CYCLE, {
// Events //todo: add pot kill trick // Events //todo: add pot kill trick
EventAccess(&logic->JabuJabusBellyClear, []{return logic->JabuJabusBellyClear || logic->CanKillEnemy(RE_BARINADE);}), EventAccess(&logic->JabuJabusBellyClear, []{return logic->CanKillEnemy(RE_BARINADE);}),
}, { }, {
// Locations // Locations
LOCATION(RC_JABU_JABUS_BELLY_BARINADE_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_BARINADE_POT_1, logic->CanBreakPots()),

View file

@ -408,7 +408,7 @@ void RegionTable_Init_ShadowTemple() {
areaTable[RR_SHADOW_TEMPLE_BOSS_ROOM] = Region("Shadow Temple Boss Room", "Shadow Temple", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_SHADOW_TEMPLE_BOSS_ROOM] = Region("Shadow Temple Boss Room", "Shadow Temple", {}, NO_DAY_NIGHT_CYCLE, {
// Events // Events
EventAccess(&logic->ShadowTempleClear, []{return logic->ShadowTempleClear || logic->CanKillEnemy(RE_BONGO_BONGO);}), EventAccess(&logic->ShadowTempleClear, []{return logic->CanKillEnemy(RE_BONGO_BONGO);}),
}, { }, {
// Locations // Locations
LOCATION(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, logic->ShadowTempleClear), LOCATION(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, logic->ShadowTempleClear),

View file

@ -556,7 +556,7 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_BOSS_ROOM] = Region("Spirit Temple Boss Room", "Spirit Temple", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_SPIRIT_TEMPLE_BOSS_ROOM] = Region("Spirit Temple Boss Room", "Spirit Temple", {}, NO_DAY_NIGHT_CYCLE, {
// Events // Events
EventAccess(&logic->SpiritTempleClear, []{return logic->SpiritTempleClear || logic->CanKillEnemy(RE_TWINROVA);}), EventAccess(&logic->SpiritTempleClear, []{return logic->CanKillEnemy(RE_TWINROVA);}),
}, { }, {
// Locations // Locations
LOCATION(RC_SPIRIT_TEMPLE_TWINROVA_HEART, logic->SpiritTempleClear), LOCATION(RC_SPIRIT_TEMPLE_TWINROVA_HEART, logic->SpiritTempleClear),

View file

@ -40,7 +40,7 @@ void RegionTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_EAST_LOWER] = Region("Water Temple East Lower", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_WATER_TEMPLE_EAST_LOWER] = Region("Water Temple East Lower", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->CanWaterTempleLowFromHigh, []{return logic->CanWaterTempleLowFromHigh || logic->CanUse(RG_ZELDAS_LULLABY);}), EventAccess(&logic->CanWaterTempleLowFromHigh, []{return logic->CanUse(RG_ZELDAS_LULLABY);}),
}, { }, {
//Locations //Locations
LOCATION(RC_WATER_TEMPLE_TORCH_POT_1, logic->CanBreakPots() && (logic->CanWaterTempleLowFromHigh || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)))), LOCATION(RC_WATER_TEMPLE_TORCH_POT_1, logic->CanBreakPots() && (logic->CanWaterTempleLowFromHigh || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)))),
@ -165,7 +165,7 @@ void RegionTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER] = Region("Water Temple Central Pillar Upper", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER] = Region("Water Temple Central Pillar Upper", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->CanWaterTempleMiddle, []{return logic->CanWaterTempleMiddle || logic->CanUse(RG_ZELDAS_LULLABY);}), EventAccess(&logic->CanWaterTempleMiddle, []{return logic->CanUse(RG_ZELDAS_LULLABY);}),
}, { }, {
//Locations //Locations
LOCATION(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, logic->CanUse(RG_LONGSHOT) || (((ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE) || logic->SmallKeys(RR_WATER_TEMPLE, 5))) || (ctx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && logic->CanUse(RG_IRON_BOOTS) && ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FAIRY_BOW)) || (logic->CanUse(RG_DINS_FIRE))))) && logic->CanWaterTempleHigh && logic->HookshotOrBoomerang())), LOCATION(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, logic->CanUse(RG_LONGSHOT) || (((ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE) || logic->SmallKeys(RR_WATER_TEMPLE, 5))) || (ctx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && logic->CanUse(RG_IRON_BOOTS) && ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FAIRY_BOW)) || (logic->CanUse(RG_DINS_FIRE))))) && logic->CanWaterTempleHigh && logic->HookshotOrBoomerang())),
@ -202,7 +202,7 @@ void RegionTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_HIGH_WATER] = Region("Water Temple High Water", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_WATER_TEMPLE_HIGH_WATER] = Region("Water Temple High Water", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->CanWaterTempleHigh, []{return logic->CanWaterTempleHigh || logic->CanUse(RG_ZELDAS_LULLABY);}), EventAccess(&logic->CanWaterTempleHigh, []{return logic->CanUse(RG_ZELDAS_LULLABY);}),
}, {}, { }, {}, {
//Exits //Exits
Entrance(RR_WATER_TEMPLE_LOBBY, []{return true;}), Entrance(RR_WATER_TEMPLE_LOBBY, []{return true;}),
@ -658,7 +658,7 @@ void RegionTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE] = Region("Water Temple MQ Dragon Room Alcove", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE] = Region("Water Temple MQ Dragon Room Alcove", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->MQWaterDragonTorches, []{return true;}), EventAccess(&logic->MQWaterDragonTorches, []{return logic->HasFireSource();}),
}, },
{ {
//Locations //Locations
@ -848,7 +848,7 @@ void RegionTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_BOSS_ROOM] = Region("Water Temple Boss Room", "Water Temple", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_WATER_TEMPLE_BOSS_ROOM] = Region("Water Temple Boss Room", "Water Temple", {}, NO_DAY_NIGHT_CYCLE, {
// Events // Events
EventAccess(&logic->WaterTempleClear, []{return logic->WaterTempleClear || logic->CanKillEnemy(RE_MORPHA);}), EventAccess(&logic->WaterTempleClear, []{return logic->CanKillEnemy(RE_MORPHA);}),
}, { }, {
// Locations // Locations
LOCATION(RC_WATER_TEMPLE_MORPHA_HEART, logic->WaterTempleClear), LOCATION(RC_WATER_TEMPLE_MORPHA_HEART, logic->WaterTempleClear),

View file

@ -14,7 +14,7 @@ void RegionTable_Init_GerudoFortress() {
//Events //Events
EventAccess(&logic->CarpenterRescue, []{return logic->CanFinishGerudoFortress();}), EventAccess(&logic->CarpenterRescue, []{return logic->CanFinishGerudoFortress();}),
EventAccess(&logic->GF_GateOpen, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), EventAccess(&logic->GF_GateOpen, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}),
EventAccess(&logic->GtG_GateOpen, []{return logic->GtG_GateOpen || (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET));}), EventAccess(&logic->GtG_GateOpen, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET);}),
}, { }, {
//Locations //Locations
LOCATION(RC_GF_CHEST, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanUse(RG_SCARECROW)) || logic->CanUse(RG_LONGSHOT)), LOCATION(RC_GF_CHEST, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanUse(RG_SCARECROW)) || logic->CanUse(RG_LONGSHOT)),

View file

@ -17,7 +17,7 @@ void RegionTable_Init_CastleGrounds() {
areaTable[RR_HYRULE_CASTLE_GROUNDS] = Region("Hyrule Castle Grounds", "Castle Grounds", {RA_HYRULE_CASTLE}, DAY_NIGHT_CYCLE, { areaTable[RR_HYRULE_CASTLE_GROUNDS] = Region("Hyrule Castle Grounds", "Castle Grounds", {RA_HYRULE_CASTLE}, DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}),
EventAccess(&logic->ButterflyFairy, []{return logic->ButterflyFairy || logic->CanUse(RG_STICKS);}), EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS);}),
EventAccess(&logic->BugRock, []{return true;}), EventAccess(&logic->BugRock, []{return true;}),
}, { }, {
//Locations //Locations

View file

@ -14,7 +14,7 @@ void RegionTable_Init_DeathMountainCrater() {
areaTable[RR_DMC_UPPER_LOCAL] = Region("DMC Upper Local", "Death Mountain Crater", {RA_DEATH_MOUNTAIN_CRATER}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_DMC_UPPER_LOCAL] = Region("DMC Upper Local", "Death Mountain Crater", {RA_DEATH_MOUNTAIN_CRATER}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->GossipStoneFairy, []{return logic->GossipStoneFairy || (logic->HasExplosives() && logic->CallGossipFairyExceptSuns() && (logic->FireTimer() >= 16 || logic->Hearts() >= 3));}), EventAccess(&logic->GossipStoneFairy, []{return logic->HasExplosives() && logic->CallGossipFairyExceptSuns() && (logic->FireTimer() >= 16 || logic->Hearts() >= 3);}),
}, { }, {
//Locations //Locations
LOCATION(RC_DMC_WALL_FREESTANDING_POH, logic->FireTimer() >= 16 || logic->Hearts() >= 3), LOCATION(RC_DMC_WALL_FREESTANDING_POH, logic->FireTimer() >= 16 || logic->Hearts() >= 3),

View file

@ -33,7 +33,7 @@ void RegionTable_Init_DeathMountainTrail() {
areaTable[RR_DEATH_MOUNTAIN_SUMMIT] = Region("Death Mountain Summit", "Death Mountain", {RA_DEATH_MOUNTAIN_TRAIL}, DAY_NIGHT_CYCLE, { areaTable[RR_DEATH_MOUNTAIN_SUMMIT] = Region("Death Mountain Summit", "Death Mountain", {RA_DEATH_MOUNTAIN_TRAIL}, DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}),
EventAccess(&logic->BugRock, []{return logic->BugRock || logic->IsChild;}), EventAccess(&logic->BugRock, []{return logic->IsChild;}),
}, { }, {
//Locations //Locations
LOCATION(RC_DMT_TRADE_BROKEN_SWORD, logic->IsAdult && logic->CanUse(RG_BROKEN_SWORD)), LOCATION(RC_DMT_TRADE_BROKEN_SWORD, logic->IsAdult && logic->CanUse(RG_BROKEN_SWORD)),

View file

@ -7,7 +7,7 @@ void RegionTable_Init_DesertColossus() {
// clang-format off // clang-format off
areaTable[RR_DESERT_COLOSSUS] = Region("Desert Colossus", "Desert Colossus", {RA_DESERT_COLOSSUS}, DAY_NIGHT_CYCLE, { areaTable[RR_DESERT_COLOSSUS] = Region("Desert Colossus", "Desert Colossus", {RA_DESERT_COLOSSUS}, DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->FairyPond, []{return logic->FairyPond || logic->CanUse(RG_SONG_OF_STORMS);}), EventAccess(&logic->FairyPond, []{return logic->CanUse(RG_SONG_OF_STORMS);}),
EventAccess(&logic->BugRock, []{return true;}), EventAccess(&logic->BugRock, []{return true;}),
}, { }, {
//Locations //Locations

View file

@ -7,7 +7,7 @@ void RegionTable_Init_GerudoValley() {
// clang-format off // clang-format off
areaTable[RR_GERUDO_VALLEY] = Region("Gerudo Valley", "Gerudo Valley", {RA_GERUDO_VALLEY}, DAY_NIGHT_CYCLE, { areaTable[RR_GERUDO_VALLEY] = Region("Gerudo Valley", "Gerudo Valley", {RA_GERUDO_VALLEY}, DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->BugRock, []{return logic->BugRock || logic->IsChild;}), EventAccess(&logic->BugRock, []{return logic->IsChild;}),
}, { }, {
//Locations //Locations
LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()),

View file

@ -8,12 +8,12 @@ void RegionTable_Init_GoronCity() {
areaTable[RR_GORON_CITY] = Region("Goron City", "Goron City", {RA_GORON_CITY}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_GORON_CITY] = Region("Goron City", "Goron City", {RA_GORON_CITY}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}),
EventAccess(&logic->StickPot, []{return logic->StickPot || logic->IsChild;}), EventAccess(&logic->StickPot, []{return logic->IsChild;}),
EventAccess(&logic->BugRock, []{return logic->BugRock || (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS));}), EventAccess(&logic->BugRock, []{return logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS);}),
EventAccess(&logic->GoronCityChildFire, []{return logic->GoronCityChildFire || (logic->IsChild && logic->CanUse(RG_DINS_FIRE));}), EventAccess(&logic->GoronCityChildFire, []{return logic->IsChild && logic->CanUse(RG_DINS_FIRE);}),
EventAccess(&logic->GCWoodsWarpOpen, []{return logic->GCWoodsWarpOpen || (logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || logic->CanUse(RG_FAIRY_BOW) || logic->HasItem(RG_GORONS_BRACELET) || logic->GoronCityChildFire);}), EventAccess(&logic->GCWoodsWarpOpen, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || logic->CanUse(RG_FAIRY_BOW) || logic->HasItem(RG_GORONS_BRACELET) || logic->GoronCityChildFire;}),
EventAccess(&logic->GCDaruniasDoorOpenChild, []{return logic->GCDaruniasDoorOpenChild || (logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY));}), EventAccess(&logic->GCDaruniasDoorOpenChild, []{return logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY);}),
EventAccess(&logic->StopGCRollingGoronAsAdult, []{return logic->StopGCRollingGoronAsAdult || (logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || (ctx->GetTrickOption(RT_GC_LINK_GORON_DINS) && logic->CanUse(RG_DINS_FIRE))));}), EventAccess(&logic->StopGCRollingGoronAsAdult, []{return logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || (ctx->GetTrickOption(RT_GC_LINK_GORON_DINS) && logic->CanUse(RG_DINS_FIRE)));}),
}, { }, {
//Locations //Locations
LOCATION(RC_GC_MAZE_LEFT_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (ctx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS))), LOCATION(RC_GC_MAZE_LEFT_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (ctx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS))),
@ -58,7 +58,7 @@ void RegionTable_Init_GoronCity() {
areaTable[RR_GC_WOODS_WARP] = Region("GC Woods Warp", "Goron City", {RA_GORON_CITY}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_GC_WOODS_WARP] = Region("GC Woods Warp", "Goron City", {RA_GORON_CITY}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->GCWoodsWarpOpen, []{return logic->GCWoodsWarpOpen || (logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE));}), EventAccess(&logic->GCWoodsWarpOpen, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}),
}, {}, { }, {}, {
//Exits //Exits
Entrance(RR_GORON_CITY, []{return logic->CanLeaveForest() && logic->GCWoodsWarpOpen;}), Entrance(RR_GORON_CITY, []{return logic->CanLeaveForest() && logic->GCWoodsWarpOpen;}),
@ -67,7 +67,7 @@ void RegionTable_Init_GoronCity() {
areaTable[RR_GC_DARUNIAS_CHAMBER] = Region("GC Darunias Chamber", "Goron City", {RA_GORON_CITY}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_GC_DARUNIAS_CHAMBER] = Region("GC Darunias Chamber", "Goron City", {RA_GORON_CITY}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->GoronCityChildFire, []{return logic->GoronCityChildFire || (logic->IsChild && logic->CanUse(RG_STICKS));}), EventAccess(&logic->GoronCityChildFire, []{return logic->IsChild && logic->CanUse(RG_STICKS);}),
}, { }, {
//Locations //Locations
LOCATION(RC_GC_DARUNIAS_JOY, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)), LOCATION(RC_GC_DARUNIAS_JOY, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)),

View file

@ -7,7 +7,7 @@ void RegionTable_Init_Graveyard() {
// clang-format off // clang-format off
areaTable[RR_THE_GRAVEYARD] = Region("The Graveyard", "The Graveyard", {RA_THE_GRAVEYARD}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_THE_GRAVEYARD] = Region("The Graveyard", "The Graveyard", {RA_THE_GRAVEYARD}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->ButterflyFairy, []{return logic->ButterflyFairy || (logic->CanUse(RG_STICKS) && logic->AtDay);}), EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}),
EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}),
EventAccess(&logic->BugRock, []{return true;}), EventAccess(&logic->BugRock, []{return true;}),
}, { }, {
@ -88,7 +88,7 @@ void RegionTable_Init_Graveyard() {
areaTable[RR_GRAVEYARD_DAMPES_GRAVE] = Region("Graveyard Dampes Grave", "Windmill and Dampes Grave", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_GRAVEYARD_DAMPES_GRAVE] = Region("Graveyard Dampes Grave", "Windmill and Dampes Grave", {}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->NutPot, []{return true;}), EventAccess(&logic->NutPot, []{return true;}),
EventAccess(&logic->DampesWindmillAccess, []{return logic->DampesWindmillAccess || (logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME));}), EventAccess(&logic->DampesWindmillAccess, []{return logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME);}),
}, { }, {
//Locations //Locations
LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, true), LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, true),

View file

@ -166,7 +166,7 @@ void RegionTable_Init_Kakariko() {
areaTable[RR_KAK_WINDMILL] = Region("Kak Windmill", "Windmill and Dampes Grave", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_KAK_WINDMILL] = Region("Kak Windmill", "Windmill and Dampes Grave", {}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->DrainWell, []{return logic->DrainWell || (logic->IsChild && logic->CanUse(RG_SONG_OF_STORMS));}), EventAccess(&logic->DrainWell, []{return logic->IsChild && logic->CanUse(RG_SONG_OF_STORMS);}),
}, { }, {
//Locations //Locations
LOCATION(RC_KAK_WINDMILL_FREESTANDING_POH, logic->CanUse(RG_BOOMERANG) || logic->DampesWindmillAccess || (logic->IsAdult && ctx->GetTrickOption(RT_KAK_ADULT_WINDMILL_POH)) || (logic->IsChild && logic->CanJumpslashExceptHammer() && ctx->GetTrickOption(RT_KAK_CHILD_WINDMILL_POH))), LOCATION(RC_KAK_WINDMILL_FREESTANDING_POH, logic->CanUse(RG_BOOMERANG) || logic->DampesWindmillAccess || (logic->IsAdult && ctx->GetTrickOption(RT_KAK_ADULT_WINDMILL_POH)) || (logic->IsChild && logic->CanJumpslashExceptHammer() && ctx->GetTrickOption(RT_KAK_CHILD_WINDMILL_POH))),

View file

@ -9,7 +9,7 @@ void RegionTable_Init_KokiriForest() {
//Events //Events
EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}),
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}),
EventAccess(&logic->ShowedMidoSwordAndShield, []{return logic->ShowedMidoSwordAndShield || (logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD));}), EventAccess(&logic->ShowedMidoSwordAndShield, []{return logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD);}),
}, { }, {
//Locations //Locations
LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild), LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild),
@ -93,7 +93,7 @@ void RegionTable_Init_KokiriForest() {
//Events //Events
EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}),
EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}),
EventAccess(&logic->ShowedMidoSwordAndShield, []{return logic->ShowedMidoSwordAndShield || (logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD));}), EventAccess(&logic->ShowedMidoSwordAndShield, []{return logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD);}),
}, { }, {
//Locations //Locations
LOCATION(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), LOCATION(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()),

View file

@ -9,10 +9,10 @@ void RegionTable_Init_LakeHylia() {
//Events //Events
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}),
EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}),
EventAccess(&logic->ButterflyFairy, []{return logic->ButterflyFairy || logic->CanUse(RG_STICKS);}), EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS);}),
EventAccess(&logic->BugShrub, []{return logic->BugShrub || (logic->IsChild && logic->CanCutShrubs());}), EventAccess(&logic->BugShrub, []{return logic->IsChild && logic->CanCutShrubs();}),
EventAccess(&logic->ChildScarecrow, []{return logic->ChildScarecrow || (logic->IsChild && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2);}), EventAccess(&logic->ChildScarecrow, []{return logic->IsChild && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2;}),
EventAccess(&logic->AdultScarecrow, []{return logic->AdultScarecrow || (logic->IsAdult && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2);}), EventAccess(&logic->AdultScarecrow, []{return logic->IsAdult && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2;}),
}, { }, {
//Locations //Locations
LOCATION(RC_LH_UNDERWATER_ITEM, logic->IsChild && logic->HasItem(RG_SILVER_SCALE)), LOCATION(RC_LH_UNDERWATER_ITEM, logic->IsChild && logic->HasItem(RG_SILVER_SCALE)),

View file

@ -7,8 +7,8 @@ void RegionTable_Init_LonLonRanch() {
// clang-format off // clang-format off
areaTable[RR_LON_LON_RANCH] = Region("Lon Lon Ranch", "Lon Lon Ranch", {RA_LON_LON_RANCH}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_LON_LON_RANCH] = Region("Lon Lon Ranch", "Lon Lon Ranch", {RA_LON_LON_RANCH}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->FreedEpona, []{return logic->FreedEpona || ((logic->HasItem(RG_CHILD_WALLET) || ctx->GetOption(RSK_SKIP_EPONA_RACE)) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay);}), EventAccess(&logic->FreedEpona, []{return (logic->HasItem(RG_CHILD_WALLET) || ctx->GetOption(RSK_SKIP_EPONA_RACE)) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay;}),
EventAccess(&logic->LinksCow, []{return logic->LinksCow || (logic->HasItem(RG_CHILD_WALLET) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay);}), EventAccess(&logic->LinksCow, []{return logic->HasItem(RG_CHILD_WALLET) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay;}),
}, { }, {
//Locations //Locations
LOCATION(RC_SONG_FROM_MALON, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER) && logic->HasItem(RG_FAIRY_OCARINA) && logic->AtDay), LOCATION(RC_SONG_FROM_MALON, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER) && logic->HasItem(RG_FAIRY_OCARINA) && logic->AtDay),

View file

@ -64,7 +64,7 @@ void RegionTable_Init_LostWoods() {
areaTable[RR_LW_BEYOND_MIDO] = Region("LW Beyond Mido", "Lost Woods", {RA_THE_LOST_WOODS}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_LW_BEYOND_MIDO] = Region("LW Beyond Mido", "Lost Woods", {RA_THE_LOST_WOODS}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->ButterflyFairy, []{return logic->ButterflyFairy || logic->CanUse(RG_STICKS);}), EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS);}),
}, { }, {
//Locations //Locations
LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, logic->IsChild && logic->CanStunDeku()), LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, logic->IsChild && logic->CanStunDeku()),

View file

@ -138,8 +138,8 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_MASK_SHOP] = Region("Market Mask Shop", "Market Mask Shop", {}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_MARKET_MASK_SHOP] = Region("Market Mask Shop", "Market Mask Shop", {}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->SkullMask, []{return logic->SkullMask || (logic->HasItem(RG_ZELDAS_LETTER) && (ctx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}), //RANDOTODO Complete mask quest does not need this location, so should be tied to link's pocket EventAccess(&logic->SkullMask, []{return logic->HasItem(RG_ZELDAS_LETTER) && (ctx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE));}), //RANDOTODO Complete mask quest does not need this location, so should be tied to link's pocket
EventAccess(&logic->MaskOfTruth, []{return logic->MaskOfTruth || (logic->SkullMask && (ctx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && logic->CanUse(RG_SARIAS_SONG) && RegionTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && logic->StoneCount() == 3)));}), EventAccess(&logic->MaskOfTruth, []{return logic->SkullMask && (ctx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && logic->CanUse(RG_SARIAS_SONG) && RegionTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && logic->StoneCount() == 3));}),
}, { }, {
//Locations //Locations
LOCATION(RC_MASK_SHOP_HINT, true), LOCATION(RC_MASK_SHOP_HINT, true),

View file

@ -9,10 +9,10 @@ void RegionTable_Init_ZorasDomain() {
//Events //Events
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}),
EventAccess(&logic->NutPot, []{return true;}), EventAccess(&logic->NutPot, []{return true;}),
EventAccess(&logic->StickPot, []{return logic->StickPot || logic->IsChild;}), EventAccess(&logic->StickPot, []{return logic->IsChild;}),
EventAccess(&logic->FishGroup, []{return logic->FishGroup || logic->IsChild;}), EventAccess(&logic->FishGroup, []{return logic->IsChild;}),
EventAccess(&logic->KingZoraThawed, []{return logic->KingZoraThawed || (logic->IsAdult && logic->BlueFire());}), EventAccess(&logic->KingZoraThawed, []{return logic->IsAdult && logic->BlueFire();}),
EventAccess(&logic->DeliverLetter, []{return logic->DeliverLetter || (logic->CanUse(RG_RUTOS_LETTER) && logic->IsChild && ctx->GetOption(RSK_ZORAS_FOUNTAIN).IsNot(RO_ZF_OPEN));}), EventAccess(&logic->DeliverLetter, []{return logic->CanUse(RG_RUTOS_LETTER) && logic->IsChild && ctx->GetOption(RSK_ZORAS_FOUNTAIN).IsNot(RO_ZF_OPEN);}),
}, { }, {
//Locations //Locations
LOCATION(RC_ZD_DIVING_MINIGAME, logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_CHILD_WALLET) && logic->IsChild), LOCATION(RC_ZD_DIVING_MINIGAME, logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_CHILD_WALLET) && logic->IsChild),

View file

@ -8,7 +8,7 @@ void RegionTable_Init_ZorasFountain() {
areaTable[RR_ZORAS_FOUNTAIN] = Region("Zoras Fountain", "Zoras Fountain", {RA_ZORAS_FOUNTAIN}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_ZORAS_FOUNTAIN] = Region("Zoras Fountain", "Zoras Fountain", {RA_ZORAS_FOUNTAIN}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}),
EventAccess(&logic->ButterflyFairy, []{return logic->ButterflyFairy || (logic->CanUse(RG_STICKS) && logic->AtDay);}), EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}),
}, { }, {
//Locations //Locations
LOCATION(RC_ZF_GS_TREE, logic->IsChild), LOCATION(RC_ZF_GS_TREE, logic->IsChild),

View file

@ -30,8 +30,8 @@ void RegionTable_Init_ZoraRiver() {
//Events //Events
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}), EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairy();}),
EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}),
EventAccess(&logic->ButterflyFairy, []{return logic->ButterflyFairy || logic->CanUse(RG_STICKS);}), EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS);}),
EventAccess(&logic->BugShrub, []{return logic->BugShrub || logic->CanCutShrubs();}), EventAccess(&logic->BugShrub, []{return logic->CanCutShrubs();}),
}, { }, {
//Locations //Locations
LOCATION(RC_ZR_MAGIC_BEAN_SALESMAN, logic->HasItem(RG_CHILD_WALLET) && logic->IsChild), LOCATION(RC_ZR_MAGIC_BEAN_SALESMAN, logic->HasItem(RG_CHILD_WALLET) && logic->IsChild),

View file

@ -1387,6 +1387,7 @@ bool Logic::SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless
static_cast<uint8_t>(GlitchDifficulty::INTERMEDIATE) || GetDifficultyValueFromString(GlitchHover) >= static_cast<uint8_t>(GlitchDifficulty::INTERMEDIATE) || GetDifficultyValueFromString(GlitchHover) >=
static_cast<uint8_t>(GlitchDifficulty::INTERMEDIATE))) { return FireTempleKeys >= requiredAmountGlitched; static_cast<uint8_t>(GlitchDifficulty::INTERMEDIATE))) { return FireTempleKeys >= requiredAmountGlitched;
}*/ }*/
// If the Fire Temple loop lock is removed, Small key Count is set to 1 before starting
return GetSmallKeyCount(SCENE_FIRE_TEMPLE) >= requiredAmountGlitchless; return GetSmallKeyCount(SCENE_FIRE_TEMPLE) >= requiredAmountGlitchless;
case RR_WATER_TEMPLE: case RR_WATER_TEMPLE:
@ -1814,7 +1815,7 @@ void Logic::ApplyItemEffect(Item& item, bool state) {
if (randoGet == RG_BOTTLE_WITH_BIG_POE) { if (randoGet == RG_BOTTLE_WITH_BIG_POE) {
BigPoes++; BigPoes++;
} }
mSaveContext->inventory.items[slot] = itemId; mSaveContext->inventory.items[slot] = static_cast<uint8_t>(itemId);
} break; } break;
case RG_RUTOS_LETTER: case RG_RUTOS_LETTER:
SetRandoInf(RAND_INF_OBTAINED_RUTOS_LETTER, state); SetRandoInf(RAND_INF_OBTAINED_RUTOS_LETTER, state);
@ -2306,7 +2307,7 @@ void Logic::SetEventChkInf(int32_t flag, bool state) {
} }
uint8_t Logic::GetGSCount() { uint8_t Logic::GetGSCount() {
return mSaveContext->inventory.gsTokens; return static_cast<uint8_t>(mSaveContext->inventory.gsTokens);
} }
uint8_t Logic::GetAmmo(uint32_t item) { uint8_t Logic::GetAmmo(uint32_t item) {
@ -2334,9 +2335,9 @@ void Logic::Reset() {
StartPerformanceTimer(PT_LOGIC_RESET); StartPerformanceTimer(PT_LOGIC_RESET);
memset(inLogic, false, sizeof(inLogic)); memset(inLogic, false, sizeof(inLogic));
// Settings-dependent variables // Settings-dependent variables
IsKeysanity = ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || IsFireLoopLocked = ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) ||
ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) ||
ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE); ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON);
// AmmoCanDrop = /*AmmoDrops.IsNot(AMMODROPS_NONE)*/ false; TODO: AmmoDrop setting // AmmoCanDrop = /*AmmoDrops.IsNot(AMMODROPS_NONE)*/ false; TODO: AmmoDrop setting
@ -2398,7 +2399,7 @@ void Logic::Reset() {
// If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in vanilla // If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in vanilla
// FiT // FiT
if (!IsKeysanity && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) { if (!IsFireLoopLocked && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) {
SetSmallKeyCount(SCENE_FIRE_TEMPLE, 1); SetSmallKeyCount(SCENE_FIRE_TEMPLE, 1);
} }
@ -2496,6 +2497,7 @@ void Logic::Reset() {
ForestOpenBossCorridor = false; ForestOpenBossCorridor = false;
ShadowTrialFirstChest = false; ShadowTrialFirstChest = false;
MQGTGMazeSwitch = false; MQGTGMazeSwitch = false;
MQGTGRightSideSwitch = false;
GTGPlatformSilverRupees = false; GTGPlatformSilverRupees = false;
MQJabuHolesRoomDoor = false; MQJabuHolesRoomDoor = false;
JabuWestTentacle = false; JabuWestTentacle = false;

View file

@ -59,7 +59,7 @@ class Logic {
bool LightTrialClear = false; bool LightTrialClear = false;
// Logical keysanity // Logical keysanity
bool IsKeysanity = false; bool IsFireLoopLocked = false;
// Bottle Count // Bottle Count
uint8_t Bottles = 0; uint8_t Bottles = 0;

View file

@ -83,11 +83,11 @@ void Option::RestoreDelayedOption() {
contextSelection = delayedSelection; contextSelection = delayedSelection;
} }
void Option::SetContextIndex(size_t idx) { void Option::SetContextIndex(uint8_t idx) {
// TODO: Set to Context's OptionValue array. // TODO: Set to Context's OptionValue array.
contextSelection = idx; contextSelection = idx;
if (contextSelection > options.size() - 1) { if (contextSelection > static_cast<uint8_t>(options.size() - 1)) {
contextSelection = options.size() - 1; contextSelection = static_cast<uint8_t>(options.size() - 1);
} }
} }
@ -105,7 +105,7 @@ bool Option::IsHidden() const {
void Option::ChangeOptions(std::vector<std::string> opts) { void Option::ChangeOptions(std::vector<std::string> opts) {
if (GetOptionIndex() >= opts.size()) { if (GetOptionIndex() >= opts.size()) {
CVarSetInteger(cvarName.c_str(), opts.size() - 1); CVarSetInteger(cvarName.c_str(), static_cast<uint8_t>(opts.size() - 1));
} }
options = std::move(opts); options = std::move(opts);
} }
@ -206,8 +206,8 @@ bool Option::RenderCheckbox() {
bool Option::RenderCombobox() { bool Option::RenderCombobox() {
bool changed = false; bool changed = false;
uint8_t selected = CVarGetInteger(cvarName.c_str(), defaultOption); uint8_t selected = CVarGetInteger(cvarName.c_str(), defaultOption);
if (selected >= options.size()) { if (selected >= static_cast<uint8_t>(options.size())) {
selected = options.size(); selected = static_cast<uint8_t>(options.size());
CVarSetInteger(cvarName.c_str(), selected); CVarSetInteger(cvarName.c_str(), selected);
changed = true; changed = true;
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
@ -231,13 +231,13 @@ bool Option::RenderSlider() {
bool changed = false; bool changed = false;
int val = CVarGetInteger(cvarName.c_str(), defaultOption); int val = CVarGetInteger(cvarName.c_str(), defaultOption);
if (val > options.size() - 1) { if (val > options.size() - 1) {
val = options.size() - 1; val = static_cast<int>(options.size()) - 1;
changed = true; changed = true;
} }
UIWidgets::IntSliderOptions widgetOptions = UIWidgets::IntSliderOptions() UIWidgets::IntSliderOptions widgetOptions = UIWidgets::IntSliderOptions()
.Color(THEME_COLOR) .Color(THEME_COLOR)
.Min(0) .Min(0)
.Max(options.size() - 1) .Max(static_cast<uint8_t>(options.size() - 1))
.Tooltip(description.c_str()) .Tooltip(description.c_str())
.Format(options[val].c_str()) .Format(options[val].c_str())
.DefaultValue(defaultOption); .DefaultValue(defaultOption);

View file

@ -241,11 +241,11 @@ class Option {
void RestoreDelayedOption(); void RestoreDelayedOption();
/** /**
* @brief Set the rando context index for this Option. Also calls `SetVariable()`. * @brief Set the rando context index for this Option.
* *
* @param idx the index to set as the selected index. * @param idx the index to set as the selected index.
*/ */
void SetContextIndex(size_t idx); void SetContextIndex(uint8_t idx);
/** /**
* @brief Hides this Option in the menu. (Not currently being used afaik, we prefer to * @brief Hides this Option in the menu. (Not currently being used afaik, we prefer to

View file

@ -65,7 +65,7 @@ const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi";
const std::string Randomizer::IceTrapRandoMessageTableID = "RandomizerIceTrap"; const std::string Randomizer::IceTrapRandoMessageTableID = "RandomizerIceTrap";
const std::string Randomizer::randoMiscHintsTableID = "RandomizerMiscHints"; const std::string Randomizer::randoMiscHintsTableID = "RandomizerMiscHints";
static const char* englishRupeeNames[190] = { static const char* englishRupeeNames[188] = {
"[P]", "[P]",
"Bad RNG Rolls", "Bad RNG Rolls",
"Baht", "Baht",
@ -111,8 +111,6 @@ static const char* englishRupeeNames[190] = {
"Dimes", "Dimes",
"Dinars", "Dinars",
"DNA", "DNA",
"Doge",
"Dogecoin",
"Doll Hairs", "Doll Hairs",
"Dollars", "Dollars",
"Dollarydoos", "Dollarydoos",
@ -258,25 +256,25 @@ static const char* englishRupeeNames[190] = {
"Zorkmids", "Zorkmids",
}; };
static const char* germanRupeeNames[80] = { static const char* germanRupeeNames[79] = {
"Baht", "Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", "Brötchen", "Cent", "Baht", "Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", "Brötchen", "Cent",
"Diamanten", "Dinar", "Diridari", "Dogecoin", "Dollar", "Draken", "ECU", "Elexit", "Diamanten", "Dinar", "Diridari", "Dollar", "Draken", "ECU", "Elexit", "Erz",
"Erz", "Erzbrocken", "Euro", "EXP", "Forint", "Franken", "Freunde", "Gil", "Erzbrocken", "Euro", "EXP", "Forint", "Franken", "Freunde", "Gil", "Gold",
"Gold", "Groschen", "Gulden", "Gummibären", "Heller", "Juwelen", "Karolin", "Kartoffeln", "Groschen", "Gulden", "Gummibären", "Heller", "Juwelen", "Karolin", "Kartoffeln", "Kies",
"Kies", "Knete", "Knochen", "Kohle", "Kraniche", "Kreuzer", "Kronen", "Kronkorken", "Knete", "Knochen", "Kohle", "Kraniche", "Kreuzer", "Kronen", "Kronkorken", "Kröten",
"Kröten", "Lira", "Mark", "Mäuse", "Monde", "Moorhühner", "Moos", "Münzen", "Lira", "Mark", "Mäuse", "Monde", "Moorhühner", "Moos", "Münzen", "Naira",
"Naira", "Penunze", "Pesa", "Pfandflaschen", "Pfennig", "Pfund", "Pilze", "Plastiks", "Penunze", "Pesa", "Pfandflaschen", "Pfennig", "Pfund", "Pilze", "Plastiks", "Pokédollar",
"Pokédollar", "Radieschen", "Rand", "Rappen", "Real", "Rial", "Riyal", "Rubine", "Radieschen", "Rand", "Rappen", "Real", "Rial", "Riyal", "Rubine", "Rupien",
"Rupien", "Saphire", "Schilling", "Seelen", "Septime", "Smaragde", "Steine", "Sterne", "Saphire", "Schilling", "Seelen", "Septime", "Smaragde", "Steine", "Sterne", "Sternis",
"Sternis", "Tael", "Taler", "Wagenchips", "Won", "Yen", "Yuan", "Zenny", "Tael", "Taler", "Wagenchips", "Won", "Yen", "Yuan", "Zenny",
}; };
static const char* frenchRupeeNames[40] = { static const char* frenchRupeeNames[39] = {
"Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", "Blés", "Bling", "Capsules", "Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", "Blés", "Bling", "Capsules",
"Centimes", "Champignons", "Clochettes", "Crédits", "Croissants", "Diamants", "Dogecoin", "Dollars", "Centimes", "Champignons", "Clochettes", "Crédits", "Croissants", "Diamants", "Dollars", "Émeraudes",
"Émeraudes", "Éthers", "Étoiles", "Euros", "Florens", "Francs", "Galds", "Gils", "Éthers", "Étoiles", "Euros", "Florens", "Francs", "Galds", "Gils", "Grouses",
"Grouses", "Halos", "Joyaux", "Lunes", "Mailles", "Munnies", "Orbes", "Orens", "Halos", "Joyaux", "Lunes", "Mailles", "Munnies", "Orbes", "Orens", "Pépètes",
"Pépètes", "Pièces", "Plastyks", "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies", "Pièces", "Plastyks", "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies",
}; };
Randomizer::Randomizer() { Randomizer::Randomizer() {
@ -357,9 +355,12 @@ std::unordered_map<s16, s16> getItemIdToItemId = {
{ GI_CLAIM_CHECK, ITEM_CLAIM_CHECK }, { GI_CLAIM_CHECK, ITEM_CLAIM_CHECK },
}; };
#ifdef _MSC_VER
#pragma optimize("", off) #pragma optimize("", off)
#else
#pragma GCC push_options #pragma GCC push_options
#pragma GCC optimize("O0") #pragma GCC optimize("O0")
#endif
bool Randomizer::SpoilerFileExists(const char* spoilerFileName) { bool Randomizer::SpoilerFileExists(const char* spoilerFileName) {
if (strcmp(spoilerFileName, "") != 0) { if (strcmp(spoilerFileName, "") != 0) {
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName)); std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
@ -372,8 +373,11 @@ bool Randomizer::SpoilerFileExists(const char* spoilerFileName) {
return false; return false;
} }
#pragma GCC pop_options #ifdef _MSC_VER
#pragma optimize("", on) #pragma optimize("", on)
#else
#pragma GCC pop_options
#endif
void Randomizer::LoadHintMessages() { void Randomizer::LoadHintMessages() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
@ -3506,9 +3510,9 @@ CrateIdentity Randomizer::IdentifyCrate(s32 sceneNum, s32 posX, s32 posZ) {
crateSceneNum = SCENE_MARKET_DAY; crateSceneNum = SCENE_MARKET_DAY;
} else if (sceneNum == SCENE_GERUDOS_FORTRESS && gPlayState->linkAgeOnLoad == 1 && posX == 310) { } else if (sceneNum == SCENE_GERUDOS_FORTRESS && gPlayState->linkAgeOnLoad == 1 && posX == 310) {
if (posZ == -1830) { if (posZ == -1830) {
posZ = -1842.0f; posZ = -1842;
} else if (posZ == -1770) { } else if (posZ == -1770) {
posZ = -1782.0f; posZ = -1782;
} }
} }
@ -3734,13 +3738,15 @@ void RandomizerSettingsWindow::DrawElement() {
} }
UIWidgets::Spacer(0); UIWidgets::Spacer(0);
ImGui::BeginDisabled((gSaveContext.gameMode != GAMEMODE_FILE_SELECT) || GameInteractor::IsSaveLoaded()); UIWidgets::ButtonOptions options = UIWidgets::ButtonOptions().Size(ImVec2(250.f, 0.f)).Color(THEME_COLOR);
if (UIWidgets::Button("Generate Randomizer", options.Disabled((gSaveContext.gameMode != GAMEMODE_FILE_SELECT) || GameInteractor::IsSaveLoaded());
UIWidgets::ButtonOptions().Size(ImVec2(250.f, 0.f)).Color(THEME_COLOR))) { if (options.disabled) {
options.DisabledTooltip("Must be on File Select to generate a randomizer seed.");
}
if (UIWidgets::Button("Generate Randomizer", options)) {
ctx->SetSpoilerLoaded(false); ctx->SetSpoilerLoaded(false);
GenerateRandomizer(CVarGetInteger(CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), 0) ? seedString : ""); GenerateRandomizer(CVarGetInteger(CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), 0) ? seedString : "");
} }
ImGui::EndDisabled();
ImGui::SameLine(); ImGui::SameLine();
if (!CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) { if (!CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) {
@ -4100,7 +4106,7 @@ void RandomizerSettingsWindow::DrawElement() {
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
} }
} }
if (ImGui::BeginTable("trickTags", showTag.size(), if (ImGui::BeginTable("trickTags", static_cast<int>(showTag.size()),
ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings |
ImGuiTableFlags_Borders)) { ImGuiTableFlags_Borders)) {
for (auto [rtTag, isShown] : showTag) { for (auto [rtTag, isShown] : showTag) {
@ -4523,6 +4529,9 @@ CustomMessage Randomizer::GetMapGetItemMessageWithHint(GetItemEntry itemEntry) {
messageEntry.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_ORDINARY].GetHintMessage()); messageEntry.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_ORDINARY].GetHintMessage());
} }
// BUG: the icon is not in the message yet so are not accounted for, so overflows are possible
messageEntry.AutoFormat();
return messageEntry; return messageEntry;
} }
@ -5568,7 +5577,7 @@ void RandomizerSettingsWindow::InitElement() {
// (special cases for rando items) // (special cases for rando items)
void Randomizer_GameplayStats_SetTimestamp(uint16_t item) { void Randomizer_GameplayStats_SetTimestamp(uint16_t item) {
u32 time = GAMEPLAYSTAT_TOTAL_TIME; u32 time = static_cast<u32>(GAMEPLAYSTAT_TOTAL_TIME);
// Have items in Link's pocket shown as being obtained at 0.1 seconds // Have items in Link's pocket shown as being obtained at 0.1 seconds
if (time == 0) { if (time == 0) {
@ -5864,7 +5873,7 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
case RG_GREG_RUPEE: case RG_GREG_RUPEE:
Rupees_ChangeBy(1); Rupees_ChangeBy(1);
Flags_SetRandomizerInf(RAND_INF_GREG_FOUND); Flags_SetRandomizerInf(RAND_INF_GREG_FOUND);
gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_FOUND_GREG] = GAMEPLAYSTAT_TOTAL_TIME; gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_FOUND_GREG] = static_cast<u32>(GAMEPLAYSTAT_TOTAL_TIME);
break; break;
case RG_TRIFORCE_PIECE: case RG_TRIFORCE_PIECE:
gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected++; gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected++;
@ -5873,7 +5882,8 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
// Teleport to credits when goal is reached. // Teleport to credits when goal is reached.
if (gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected == if (gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected ==
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED) + 1)) { (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED) + 1)) {
gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED] = GAMEPLAYSTAT_TOTAL_TIME; gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED] =
static_cast<u32>(GAMEPLAYSTAT_TOTAL_TIME);
gSaveContext.ship.stats.gameComplete = 1; gSaveContext.ship.stats.gameComplete = 1;
Flags_SetRandomizerInf(RAND_INF_GRANT_GANONS_BOSSKEY); Flags_SetRandomizerInf(RAND_INF_GRANT_GANONS_BOSSKEY);
Play_PerformSave(play); Play_PerformSave(play);
@ -5906,12 +5916,12 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
case RG_DEKU_STICK_BAG: case RG_DEKU_STICK_BAG:
Inventory_ChangeUpgrade(UPG_STICKS, 1); Inventory_ChangeUpgrade(UPG_STICKS, 1);
INV_CONTENT(ITEM_STICK) = ITEM_STICK; INV_CONTENT(ITEM_STICK) = ITEM_STICK;
AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); AMMO(ITEM_STICK) = static_cast<int8_t>(CUR_CAPACITY(UPG_STICKS));
break; break;
case RG_DEKU_NUT_BAG: case RG_DEKU_NUT_BAG:
Inventory_ChangeUpgrade(UPG_NUTS, 1); Inventory_ChangeUpgrade(UPG_NUTS, 1);
INV_CONTENT(ITEM_NUT) = ITEM_NUT; INV_CONTENT(ITEM_NUT) = ITEM_NUT;
AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS); AMMO(ITEM_NUT) = static_cast<int8_t>(CUR_CAPACITY(UPG_NUTS));
break; break;
default: default:
LUSLOG_WARN("Randomizer_Item_Give didn't have behaviour specified for getItemId=%d", item); LUSLOG_WARN("Randomizer_Item_Give didn't have behaviour specified for getItemId=%d", item);

View file

@ -1886,16 +1886,16 @@ static std::set<std::string> rainbowCVars = {
int hue = 0; int hue = 0;
void RainbowTick() { void RainbowTick() {
float freqHue = hue * 2 * M_PI / (360 * CVarGetFloat(CVAR_COSMETIC("RainbowSpeed"), 0.6f)); float freqHue = hue * 2 * M_PIf / (360 * CVarGetFloat(CVAR_COSMETIC("RainbowSpeed"), 0.6f));
for (auto& cvar : rainbowCVars) { for (auto& cvar : rainbowCVars) {
if (CVarGetInteger((cvar + ".Rainbow").c_str(), 0) == 0) { if (CVarGetInteger((cvar + ".Rainbow").c_str(), 0) == 0) {
continue; continue;
} }
Color_RGBA8 newColor; Color_RGBA8 newColor;
newColor.r = sin(freqHue + 0) * 127 + 128; newColor.r = static_cast<uint8_t>(sin(freqHue + 0) * 127) + 128;
newColor.g = sin(freqHue + (2 * M_PI / 3)) * 127 + 128; newColor.g = static_cast<uint8_t>(sin(freqHue + (2 * M_PI / 3)) * 127) + 128;
newColor.b = sin(freqHue + (4 * M_PI / 3)) * 127 + 128; newColor.b = static_cast<uint8_t>(sin(freqHue + (4 * M_PI / 3)) * 127) + 128;
newColor.a = 255; newColor.a = 255;
CVarSetColor((cvar + ".Value").c_str(), newColor); CVarSetColor((cvar + ".Value").c_str(), newColor);
@ -1961,7 +1961,7 @@ void RecalculateAvailableChecks() {
StartPerformanceTimer(PT_RECALCULATE_AVAILABLE_CHECKS); StartPerformanceTimer(PT_RECALCULATE_AVAILABLE_CHECKS);
std::vector<RandomizerCheck> targetLocations; std::vector<RandomizerCheck> targetLocations;
targetLocations.reserve(RR_MAX); targetLocations.reserve(RC_MAX);
for (auto& location : Rando::StaticData::GetLocationTable()) { for (auto& location : Rando::StaticData::GetLocationTable()) {
RandomizerCheck rc = location.GetRandomizerCheck(); RandomizerCheck rc = location.GetRandomizerCheck();
Rando::ItemLocation* itemLocation = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc); Rando::ItemLocation* itemLocation = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc);
@ -1973,16 +1973,9 @@ void RecalculateAvailableChecks() {
std::vector<RandomizerCheck> availableChecks = ReachabilitySearch(targetLocations, RG_NONE, true); std::vector<RandomizerCheck> availableChecks = ReachabilitySearch(targetLocations, RG_NONE, true);
for (auto& rc : availableChecks) { for (auto& rc : availableChecks) {
const auto& location = Rando::StaticData::GetLocation(rc);
const auto& itemLocation = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc); const auto& itemLocation = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc);
if (location->GetRCType() == RCTYPE_SHOP && itemLocation->GetCheckStatus() == RCSHOW_IDENTIFIED) {
if (CanBuyAnother(rc)) {
itemLocation->SetAvailable(true); itemLocation->SetAvailable(true);
} }
} else {
itemLocation->SetAvailable(true);
}
}
totalChecksAvailable = 0; totalChecksAvailable = 0;
for (auto& [rcArea, vec] : checksByArea) { for (auto& [rcArea, vec] : checksByArea) {
@ -2108,8 +2101,11 @@ void CheckTrackerSettingsWindow::DrawElement() {
"with your current progress.") "with your current progress.")
.Color(THEME_COLOR))) { .Color(THEME_COLOR))) {
enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0); enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0);
if (GameInteractor::IsSaveLoaded(true)) {
RecalculateAvailableChecks(); RecalculateAvailableChecks();
} }
}
ImGui::EndDisabled(); ImGui::EndDisabled();
// Filtering settings // Filtering settings

View file

@ -382,7 +382,7 @@ const EntranceData entranceData[] = {
}; };
// Check if Link is in the area and return that scene/entrance for tracking // Check if Link is in the area and return that scene/entrance for tracking
s8 LinkIsInArea(const EntranceData* entrance) { int16_t LinkIsInArea(const EntranceData* entrance) {
bool result = false; bool result = false;
if (gPlayState == nullptr) { if (gPlayState == nullptr) {

View file

@ -654,17 +654,17 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) {
void DrawEquip(ItemTrackerItem item) { void DrawEquip(ItemTrackerItem item) {
bool hasEquip = HasEquipment(item); bool hasEquip = HasEquipment(item);
int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); float iconSize = static_cast<float>(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36));
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
hasEquip && IsValidSaveFile() ? item.name : item.nameFaded), hasEquip && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(iconSize, iconSize), ImVec2(0.0f, 0.0f), ImVec2(1, 1));
Tooltip(SohUtils::GetItemName(item.id).c_str()); Tooltip(SohUtils::GetItemName(item.id).c_str());
} }
void DrawQuest(ItemTrackerItem item) { void DrawQuest(ItemTrackerItem item) {
bool hasQuestItem = HasQuestItem(item); bool hasQuestItem = HasQuestItem(item);
int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); float iconSize = static_cast<float>(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36));
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded), hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded),
@ -682,7 +682,7 @@ void DrawQuest(ItemTrackerItem item) {
void DrawItem(ItemTrackerItem item) { void DrawItem(ItemTrackerItem item) {
uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE; uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE;
int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); float iconSize = static_cast<float>(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36));
bool hasItem = actualItemId != ITEM_NONE; bool hasItem = actualItemId != ITEM_NONE;
std::string itemName = ""; std::string itemName = "";
@ -999,7 +999,7 @@ void DrawBottle(ItemTrackerItem item) {
item = actualItemTrackerItemMap[actualItemId]; item = actualItemTrackerItemMap[actualItemId];
} }
int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); float iconSize = static_cast<float>(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36));
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
hasItem && IsValidSaveFile() ? item.name : item.nameFaded), hasItem && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
@ -1011,7 +1011,7 @@ void DrawDungeonItem(ItemTrackerItem item) {
uint32_t itemId = item.id; uint32_t itemId = item.id;
ImU32 dungeonColor = IM_COL_WHITE; ImU32 dungeonColor = IM_COL_WHITE;
uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential
int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); float iconSize = static_cast<float>(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36));
bool hasItem = GameInteractor::IsSaveLoaded() ? (bitMask & gSaveContext.inventory.dungeonItems[item.data]) : false; bool hasItem = GameInteractor::IsSaveLoaded() ? (bitMask & gSaveContext.inventory.dungeonItems[item.data]) : false;
bool hasSmallKey = GameInteractor::IsSaveLoaded() ? ((gSaveContext.inventory.dungeonKeys[item.data]) >= 0) : false; bool hasSmallKey = GameInteractor::IsSaveLoaded() ? ((gSaveContext.inventory.dungeonKeys[item.data]) >= 0) : false;
ImGui::BeginGroup(); ImGui::BeginGroup();
@ -1062,19 +1062,19 @@ void DrawDungeonItem(ItemTrackerItem item) {
} }
void DrawSong(ItemTrackerItem item) { void DrawSong(ItemTrackerItem item) {
int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); float iconSize = static_cast<float>(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36));
ImVec2 p = ImGui::GetCursorScreenPos(); ImVec2 p = ImGui::GetCursorScreenPos();
bool hasSong = HasSong(item); bool hasSong = HasSong(item);
ImGui::SetCursorScreenPos(ImVec2(p.x + 6, p.y)); ImGui::SetCursorScreenPos(ImVec2(p.x + 6, p.y));
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(
hasSong && IsValidSaveFile() ? item.name : item.nameFaded), hasSong && IsValidSaveFile() ? item.name : item.nameFaded),
ImVec2(iconSize / 1.5, iconSize), ImVec2(0, 0), ImVec2(1, 1)); ImVec2(iconSize / 1.5f, iconSize), ImVec2(0, 0), ImVec2(1, 1));
Tooltip(SohUtils::GetQuestItemName(item.id).c_str()); Tooltip(SohUtils::GetQuestItemName(item.id).c_str());
} }
void DrawNotes(bool resizeable = false) { void DrawNotes(bool resizeable = false) {
ImGui::BeginGroup(); ImGui::BeginGroup();
int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); float iconSize = static_cast<float>(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36));
int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12); int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12);
struct ItemTrackerNotes { struct ItemTrackerNotes {
@ -1097,7 +1097,7 @@ void DrawNotes(bool resizeable = false) {
} }
}; };
ImVec2 size = resizeable ? ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y) ImVec2 size = resizeable ? ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y)
: ImVec2(((iconSize + iconSpacing) * 6) - 8, 200); : ImVec2(((iconSize + iconSpacing) * 6) - 8.0f, 200.0f);
if (GameInteractor::IsSaveLoaded()) { if (GameInteractor::IsSaveLoaded()) {
if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size,
ImGuiInputTextFlags_AllowTabInput)) { ImGuiInputTextFlags_AllowTabInput)) {
@ -1169,7 +1169,7 @@ void EndFloatingWindows() {
* Takes in a vector of ItemTrackerItem and draws them in rows of N items * Takes in a vector of ItemTrackerItem and draws them in rows of N items
*/ */
void DrawItemsInRows(std::vector<ItemTrackerItem> items, int columns = 6) { void DrawItemsInRows(std::vector<ItemTrackerItem> items, int columns = 6) {
int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); float iconSize = static_cast<float>(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36));
int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12); int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12);
int topPadding = int topPadding =
(CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW) ? 20 : 0; (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW) ? 20 : 0;
@ -1178,7 +1178,7 @@ void DrawItemsInRows(std::vector<ItemTrackerItem> items, int columns = 6) {
int row = i / columns; int row = i / columns;
int column = i % columns; int column = i % columns;
ImGui::SetCursorPos( ImGui::SetCursorPos(
ImVec2((column * (iconSize + iconSpacing) + 8), (row * (iconSize + iconSpacing)) + 8 + topPadding)); ImVec2((column * (iconSize + iconSpacing) + 8.0f), (row * (iconSize + iconSpacing)) + 8.0f + topPadding));
items[i].drawFunc(items[i]); items[i].drawFunc(items[i]);
} }
} }
@ -1192,10 +1192,10 @@ void DrawItemsInACircle(std::vector<ItemTrackerItem> items) {
int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12); int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12);
ImVec2 max = ImGui::GetWindowContentRegionMax(); ImVec2 max = ImGui::GetWindowContentRegionMax();
float radius = (iconSize + iconSpacing) * 2; float radius = (iconSize + iconSpacing) * 2.0f;
for (int i = 0; i < items.size(); i++) { for (int i = 0; i < items.size(); i++) {
float angle = (float)i / items.size() * 2.0f * M_PI; float angle = static_cast<float>(i / items.size() * 2.0f * M_PI);
float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f; float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f;
float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f; float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f;
ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36) - 8) / 2.0f, y + 4)); ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36) - 8) / 2.0f, y + 4));
@ -1209,14 +1209,12 @@ void DrawItemsInACircle(std::vector<ItemTrackerItem> items) {
* to then call DrawItemsInRows * to then call DrawItemsInRows
*/ */
std::vector<ItemTrackerItem> GetDungeonItemsVector(std::vector<ItemTrackerDungeon> dungeons, int columns = 6) { std::vector<ItemTrackerItem> GetDungeonItemsVector(std::vector<ItemTrackerDungeon> dungeons, int columns = 6) {
int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36);
int iconSpacing = CVarGetInteger(CVAR_TRACKER_ITEM("IconSpacing"), 12);
std::vector<ItemTrackerItem> dungeonItems = {}; std::vector<ItemTrackerItem> dungeonItems = {};
int rowCount = 0; int rowCount = 0;
for (int i = 0; i < dungeons.size(); i++) { for (int i = 0; i < dungeons.size(); i++) {
if (dungeons[i].items.size() > rowCount) if (dungeons[i].items.size() > rowCount)
rowCount = dungeons[i].items.size(); rowCount = static_cast<int32_t>(dungeons[i].items.size());
} }
for (int i = 0; i < rowCount; i++) { for (int i = 0; i < rowCount; i++) {
@ -1453,7 +1451,7 @@ void ItemTrackerSaveFile(SaveContext* saveContext, int sectionID, bool fullSave)
void ItemTrackerLoadFile() { void ItemTrackerLoadFile() {
std::string initialTrackerNotes = ""; std::string initialTrackerNotes = "";
SaveManager::Instance->LoadData("personalNotes", initialTrackerNotes); SaveManager::Instance->LoadData("personalNotes", initialTrackerNotes);
itemTrackerNotes.resize(initialTrackerNotes.length() + 1); itemTrackerNotes.resize(static_cast<int>(initialTrackerNotes.length() + 1));
if (initialTrackerNotes != "") { if (initialTrackerNotes != "") {
SohUtils::CopyStringToCharArray(itemTrackerNotes.Data, initialTrackerNotes.c_str(), itemTrackerNotes.size()); SohUtils::CopyStringToCharArray(itemTrackerNotes.Data, initialTrackerNotes.c_str(), itemTrackerNotes.size());
} else { } else {
@ -1516,8 +1514,9 @@ void ItemTrackerWindow::DrawElement() {
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_MAIN_WINDOW && SECTION_DISPLAY_MAIN_WINDOW &&
(CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING &&
CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) ==
TRACKER_DISPLAY_ALWAYS) { TRACKER_DISPLAY_ALWAYS)) {
DrawNotes(); DrawNotes();
} }
EndFloatingWindows(); EndFloatingWindows();
@ -1626,7 +1625,10 @@ void ItemTrackerWindow::DrawElement() {
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) == if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Notes"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_SEPARATE && SECTION_DISPLAY_SEPARATE &&
CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW ||
(CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING &&
CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) !=
TRACKER_DISPLAY_COMBO_BUTTON))) {
ImGui::SetNextWindowSize(ImVec2(400, 300), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(400, 300), ImGuiCond_FirstUseEver);
BeginFloatingWindows("Personal Notes", ImGuiWindowFlags_NoFocusOnAppearing); BeginFloatingWindows("Personal Notes", ImGuiWindowFlags_NoFocusOnAppearing);
DrawNotes(true); DrawNotes(true);
@ -1927,7 +1929,10 @@ void ItemTrackerSettingsWindow::DrawElement() {
shouldUpdateVectors = true; shouldUpdateVectors = true;
} }
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW ||
(CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING &&
CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) !=
TRACKER_DISPLAY_COMBO_BUTTON)) {
if (CVarCombobox("Personal notes", CVAR_TRACKER_ITEM("DisplayType.Notes"), displayTypes, if (CVarCombobox("Personal notes", CVAR_TRACKER_ITEM("DisplayType.Notes"), displayTypes,
ComboboxOptions() ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_HIDDEN) .DefaultIndex(SECTION_DISPLAY_HIDDEN)

View file

@ -22,7 +22,7 @@ void StartingItemGive(GetItemEntry getItemEntry, RandomizerCheck randomizerCheck
if (getItemEntry.getItemId == GI_SWORD_BGS) { if (getItemEntry.getItemId == GI_SWORD_BGS) {
gSaveContext.bgsFlag = true; gSaveContext.bgsFlag = true;
} }
Item_Give(NULL, getItemEntry.itemId); Item_Give(NULL, static_cast<uint8_t>(getItemEntry.itemId));
} else if (getItemEntry.modIndex == MOD_RANDOMIZER) { } else if (getItemEntry.modIndex == MOD_RANDOMIZER) {
if (getItemEntry.getItemId == RG_ICE_TRAP) { if (getItemEntry.getItemId == RG_ICE_TRAP) {
gSaveContext.ship.pendingIceTrapCount++; gSaveContext.ship.pendingIceTrapCount++;
@ -269,9 +269,9 @@ extern "C" void Randomizer_InitSaveFile() {
// Remove One Time Scrubs with Scrubsanity off // Remove One Time Scrubs with Scrubsanity off
if (Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_OFF) { if (Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_OFF) {
Flags_SetRandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE); Flags_SetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE);
Flags_SetRandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT); Flags_SetInfTable(INFTABLE_BOUGHT_STICK_UPGRADE);
Flags_SetRandomizerInf(RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO); Flags_SetInfTable(INFTABLE_BOUGHT_NUT_UPGRADE);
} }
int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get(); int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get();

View file

@ -24,7 +24,7 @@ std::vector<std::string> NumOpts(const int min, const int max, const int step =
} }
std::vector<std::string> MultiVecOpts(const std::vector<std::vector<std::string>>& optionsVector) { std::vector<std::string> MultiVecOpts(const std::vector<std::vector<std::string>>& optionsVector) {
uint32_t totalSize = 0; size_t totalSize = 0;
for (const auto& vector : optionsVector) { for (const auto& vector : optionsVector) {
totalSize += vector.size(); totalSize += vector.size();
} }
@ -250,7 +250,7 @@ void Settings::CreateOptions() {
OPT_U8(RSK_LACS_REWARD_COUNT, "GCBK Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardCount"), "", WidgetType::Slider, 9, true); OPT_U8(RSK_LACS_REWARD_COUNT, "GCBK Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardCount"), "", WidgetType::Slider, 9, true);
OPT_U8(RSK_LACS_DUNGEON_COUNT, "GCBK Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), "", WidgetType::Slider, 8, true); OPT_U8(RSK_LACS_DUNGEON_COUNT, "GCBK Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), "", WidgetType::Slider, 8, true);
OPT_U8(RSK_LACS_TOKEN_COUNT, "GCBK Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsTokenCount"), "", WidgetType::Slider, 100, true); OPT_U8(RSK_LACS_TOKEN_COUNT, "GCBK Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsTokenCount"), "", WidgetType::Slider, 100, true);
OPT_U8(RSK_LACS_OPTIONS, "GCBK LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), "", WidgetType::Combobox, RO_LACS_STANDARD_REWARD); OPT_U8(RSK_LACS_OPTIONS, "GCBK LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), mOptionDescriptions[RSK_LACS_OPTIONS], WidgetType::Combobox, RO_LACS_STANDARD_REWARD);
OPT_U8(RSK_KEYRINGS, "Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF); OPT_U8(RSK_KEYRINGS, "Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF);
OPT_U8(RSK_KEYRINGS_RANDOM_COUNT, "Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WidgetType::Slider, 8); OPT_U8(RSK_KEYRINGS_RANDOM_COUNT, "Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WidgetType::Slider, 8);
OPT_U8(RSK_KEYRINGS_GERUDO_FORTRESS, "Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WidgetType::Combobox, 0); OPT_U8(RSK_KEYRINGS_GERUDO_FORTRESS, "Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WidgetType::Combobox, 0);
@ -2638,7 +2638,7 @@ void Context::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocation
mqSet += 1; mqSet += 1;
break; break;
case RO_MQ_SET_RANDOM: case RO_MQ_SET_RANDOM:
randMQOption.push_back(i); randMQOption.push_back(static_cast<uint8_t>(i));
dungeons[i]->SetDungeonKnown(false); dungeons[i]->SetDungeonKnown(false);
break; break;
default: default:
@ -2659,7 +2659,7 @@ void Context::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocation
// otherwise, make everything a possibility and unknown // otherwise, make everything a possibility and unknown
} else { } else {
for (size_t i = 0; i < dungeons.size(); i++) { for (size_t i = 0; i < dungeons.size(); i++) {
randMQOption.push_back(i); randMQOption.push_back(static_cast<uint8_t>(i));
dungeons[i]->SetDungeonKnown(false); dungeons[i]->SetDungeonKnown(false);
mOptions[dungeons[i]->GetMQSetting()].Set(RO_MQ_SET_RANDOM); mOptions[dungeons[i]->GetMQSetting()].Set(RO_MQ_SET_RANDOM);
} }

View file

@ -13,12 +13,14 @@ extern "C" {
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" #include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
#include "src/overlays/actors/ovl_En_Owl/z_en_owl.h" #include "src/overlays/actors/ovl_En_Owl/z_en_owl.h"
#include "src/overlays/actors/ovl_En_Go2/z_en_go2.h" #include "src/overlays/actors/ovl_En_Go2/z_en_go2.h"
#include "src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.h"
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h" #include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
#include "src/overlays/actors/ovl_En_Ma1/z_en_ma1.h" #include "src/overlays/actors/ovl_En_Ma1/z_en_ma1.h"
#include "src/overlays/actors/ovl_En_Ru2/z_en_ru2.h" #include "src/overlays/actors/ovl_En_Ru2/z_en_ru2.h"
#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h" #include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
#include "src/overlays/actors/ovl_En_Box/z_en_box.h" #include "src/overlays/actors/ovl_En_Box/z_en_box.h"
#include "src/overlays/actors/ovl_Demo_Im/z_demo_im.h" #include "src/overlays/actors/ovl_Demo_Im/z_demo_im.h"
#include "src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.h"
#include "src/overlays/actors/ovl_En_Sa/z_en_sa.h" #include "src/overlays/actors/ovl_En_Sa/z_en_sa.h"
#include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h" #include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h"
#include "src/overlays/actors/ovl_En_Tk/z_en_tk.h" #include "src/overlays/actors/ovl_En_Tk/z_en_tk.h"
@ -217,6 +219,25 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), IS_RANDO) && if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), IS_RANDO) &&
(entranceFlag != EVENTCHKINF_EPONA_OBTAINED) && entranceIndex != ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE) { (entranceFlag != EVENTCHKINF_EPONA_OBTAINED) && entranceIndex != ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE) {
*should = false; *should = false;
// Check for dispulsion of Ganon's Tower barrier
switch (entranceIndex) {
case ENTR_INSIDE_GANONS_CASTLE_2:
case ENTR_INSIDE_GANONS_CASTLE_3:
case ENTR_INSIDE_GANONS_CASTLE_4:
case ENTR_INSIDE_GANONS_CASTLE_5:
case ENTR_INSIDE_GANONS_CASTLE_6:
case ENTR_INSIDE_GANONS_CASTLE_7:
if (Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FOREST_TRIAL) &&
Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_WATER_TRIAL) &&
Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_SHADOW_TRIAL) &&
Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FIRE_TRIAL) &&
Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_LIGHT_TRIAL) &&
Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_SPIRIT_TRIAL)) {
Flags_SetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER);
}
break;
}
} }
break; break;
} }
@ -275,6 +296,11 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
} }
switch (actor->id) { switch (actor->id) {
case ACTOR_OBJ_SWITCH: { case ACTOR_OBJ_SWITCH: {
if ((actor->params == 8224 && gPlayState->sceneNum == SCENE_DODONGOS_CAVERN) ||
(actor->params == 6979 && gPlayState->sceneNum == SCENE_WATER_TEMPLE) &&
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) {
break;
}
ObjSwitch* switchActor = (ObjSwitch*)actor; ObjSwitch* switchActor = (ObjSwitch*)actor;
switchActor->cooldownTimer = 0; switchActor->cooldownTimer = 0;
*should = false; *should = false;
@ -349,6 +375,11 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
} }
break; break;
} }
case VB_FREEZE_LINK_FOR_FOREST_PILLARS:
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
*should = false;
}
break;
case VB_SHOW_TITLE_CARD: case VB_SHOW_TITLE_CARD:
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), IS_RANDO)) {
*should = false; *should = false;
@ -441,6 +472,26 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
*should = false; *should = false;
} }
break; break;
case VB_PLAY_DISPEL_BARRIER_CS: {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
static s16 trialEntrances[] = {
0,
ENTR_INSIDE_GANONS_CASTLE_3,
ENTR_INSIDE_GANONS_CASTLE_6,
ENTR_INSIDE_GANONS_CASTLE_5,
ENTR_INSIDE_GANONS_CASTLE_4,
ENTR_INSIDE_GANONS_CASTLE_7,
ENTR_INSIDE_GANONS_CASTLE_2,
};
RateLimitedSuccessChime();
DemoKekkai* kekkai = va_arg(args, DemoKekkai*);
gPlayState->nextEntranceIndex = trialEntrances[kekkai->actor.params];
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;
*should = false;
}
break;
}
case VB_OWL_INTERACTION: { case VB_OWL_INTERACTION: {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), IS_RANDO) && *should) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), IS_RANDO) && *should) {
EnOwl* enOwl = va_arg(args, EnOwl*); EnOwl* enOwl = va_arg(args, EnOwl*);
@ -720,6 +771,18 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
break; break;
} }
case VB_PLAY_GATE_OPENING_OR_CLOSING_CS: {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
EnHeishi2* enHeishi2 = va_arg(args, EnHeishi2*);
enHeishi2->unk_2F2[0] = 0;
// The second argument determines whether the vanilla code should be run anyway. It
// should be set to `true` ONLY IF said code calls `Play_ClearCamera`, false otherwise.
bool clearCamera = (bool)va_arg(args, int);
*should = clearCamera && enHeishi2->cameraId != MAIN_CAM;
}
break;
}
case VB_PLAY_RAINBOW_BRIDGE_CS: { case VB_PLAY_RAINBOW_BRIDGE_CS: {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
*should = false; *should = false;

View file

@ -40,6 +40,7 @@
#include "z64.h" #include "z64.h"
#include "macros.h" #include "macros.h"
#include "Fonts.h" #include "Fonts.h"
#include "window/FileDropMgr.h"
#include "window/gui/resource/Font.h" #include "window/gui/resource/Font.h"
#include <utils/StringHelper.h> #include <utils/StringHelper.h>
#include "Enhancements/custom-message/CustomMessageManager.h" #include "Enhancements/custom-message/CustomMessageManager.h"
@ -51,7 +52,7 @@
#include "Extractor/Extract.h" #include "Extractor/Extract.h"
#endif #endif
#include <Fast3D/gfx_pc.h> #include <Fast3D/interpreter.h>
#ifdef __APPLE__ #ifdef __APPLE__
#include <SDL_scancode.h> #include <SDL_scancode.h>
@ -307,6 +308,7 @@ OTRGlobals::OTRGlobals() {
context->InitGfxDebugger(); context->InitGfxDebugger();
context->InitConfiguration(); context->InitConfiguration();
context->InitConsoleVariables(); context->InitConsoleVariables();
context->InitFileDropMgr();
// tell LUS to reserve 3 SoH specific threads (Game, Audio, Save) // tell LUS to reserve 3 SoH specific threads (Game, Audio, Save)
context->InitResourceManager(OTRFiles, {}, 3); context->InitResourceManager(OTRFiles, {}, 3);
@ -1432,13 +1434,13 @@ extern "C" void Graph_StartFrame() {
} }
#endif #endif
if (CVarGetInteger(CVAR_NEW_FILE_DROPPED, 0)) { auto dropMgr = Ship::Context::GetInstance()->GetFileDropMgr();
std::string filePath = SohUtils::Sanitize(CVarGetString(CVAR_DROPPED_FILE, "")); if (dropMgr->FileDropped()) {
std::string filePath = dropMgr->GetDroppedFile();
if (!filePath.empty()) { if (!filePath.empty()) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnFileDropped>(filePath); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnFileDropped>(filePath);
} }
CVarClear(CVAR_NEW_FILE_DROPPED); dropMgr->ClearDroppedFile();
CVarClear(CVAR_DROPPED_FILE);
} }
} }
@ -1897,7 +1899,7 @@ extern "C" void OTRControllerCallback(uint8_t rumble) {
} }
extern "C" float OTRGetAspectRatio() { extern "C" float OTRGetAspectRatio() {
return gfx_current_dimensions.aspect_ratio; return Ship::Context::GetInstance()->GetWindow()->GetAspectRatio();
} }
extern "C" float OTRGetDimensionFromLeftEdge(float v) { extern "C" float OTRGetDimensionFromLeftEdge(float v) {
@ -1910,12 +1912,34 @@ extern "C" float OTRGetDimensionFromRightEdge(float v) {
// Gets the width of the current render target area // Gets the width of the current render target area
extern "C" uint32_t OTRGetGameRenderWidth() { extern "C" uint32_t OTRGetGameRenderWidth() {
return gfx_current_dimensions.width; auto fastWnd = dynamic_pointer_cast<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow());
auto intP = fastWnd->GetInterpreterWeak().lock();
if (!intP) {
assert(false && "Lost reference to Fast::Interpreter");
return 320;
}
uint32_t height, width;
intP->GetCurDimensions(&width, &height);
return width;
} }
// Gets the height of the current render target area // Gets the height of the current render target area
extern "C" uint32_t OTRGetGameRenderHeight() { extern "C" uint32_t OTRGetGameRenderHeight() {
return gfx_current_dimensions.height; auto fastWnd = dynamic_pointer_cast<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow());
auto intP = fastWnd->GetInterpreterWeak().lock();
if (!intP) {
assert(false && "Lost reference to Fast::Interpreter");
return 240;
}
uint32_t height, width;
intP->GetCurDimensions(&width, &height);
return height;
} }
f32 floorf(f32 x); // RANDOTODO False positive error "allowing all exceptions is incompatible with previous function" f32 floorf(f32 x); // RANDOTODO False positive error "allowing all exceptions is incompatible with previous function"
@ -2421,15 +2445,15 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
// animation until the text box auto-dismisses. // animation until the text box auto-dismisses.
// RANDOTODO: Implement a way to determine if an item came from a skulltula and // RANDOTODO: Implement a way to determine if an item came from a skulltula and
// inject the auto-dismiss control code if it did. // inject the auto-dismiss control code if it did.
if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && bool gsTokensShuffled = Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF;
!(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF)) { if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && !(IS_RANDO && gsTokensShuffled)) {
textId = TEXT_GS_NO_FREEZE; textId = TEXT_GS_NO_FREEZE;
} else { } else {
textId = TEXT_GS_FREEZE; textId = TEXT_GS_FREEZE;
} }
// In vanilla, GS token count is incremented prior to the text box displaying // In vanilla, GS token count is incremented prior to the text box displaying
// In rando we need to bump the token count by one to show the correct count // In rando we need to bump the token count by one to show the correct count
s16 gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); s16 gsCount = gSaveContext.inventory.gsTokens + ((IS_RANDO && gsTokensShuffled) ? 1 : 0);
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED);
messageEntry.Replace("[[gsCount]]", std::to_string(gsCount)); messageEntry.Replace("[[gsCount]]", std::to_string(gsCount));
} else if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && } else if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 &&
@ -2494,11 +2518,23 @@ extern "C" void EntranceTracker_SetLastEntranceOverride(s16 entranceIndex) {
} }
extern "C" void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement) { extern "C" void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement) {
gfx_register_blended_texture(name, mask, replacement); if (auto intP = dynamic_pointer_cast<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow())
->GetInterpreterWeak()
.lock()) {
intP->RegisterBlendedTexture(name, mask, replacement);
} else {
assert(false && "Lost reference to Fast::Interpreter");
}
} }
extern "C" void Gfx_UnregisterBlendedTexture(const char* name) { extern "C" void Gfx_UnregisterBlendedTexture(const char* name) {
gfx_unregister_blended_texture(name); if (auto intP = dynamic_pointer_cast<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow())
->GetInterpreterWeak()
.lock()) {
intP->UnregisterBlendedTexture(name);
} else {
assert(false && "Lost reference to Fast::Interpreter");
}
} }
extern "C" void Gfx_TextureCacheDelete(const uint8_t* texAddr) { extern "C" void Gfx_TextureCacheDelete(const uint8_t* texAddr) {
@ -2512,7 +2548,13 @@ extern "C" void Gfx_TextureCacheDelete(const uint8_t* texAddr) {
texAddr = (const uint8_t*)ResourceMgr_GetResourceDataByNameHandlingMQ(imgName); texAddr = (const uint8_t*)ResourceMgr_GetResourceDataByNameHandlingMQ(imgName);
} }
gfx_texture_cache_delete(texAddr); if (auto intP = dynamic_pointer_cast<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow())
->GetInterpreterWeak()
.lock()) {
intP->TextureCacheDelete(texAddr);
} else {
assert(false && "Lost reference to Fast::Interpreter");
}
} }
void SoH_ProcessDroppedFiles(std::string filePath) { void SoH_ProcessDroppedFiles(std::string filePath) {

View file

@ -15,6 +15,11 @@
#define BTN_CUSTOM_OCARINA_PITCH_UP ((CONTROLLERBUTTONS_T)0x00400000) #define BTN_CUSTOM_OCARINA_PITCH_UP ((CONTROLLERBUTTONS_T)0x00400000)
#define BTN_CUSTOM_OCARINA_PITCH_DOWN ((CONTROLLERBUTTONS_T)0x00800000) #define BTN_CUSTOM_OCARINA_PITCH_DOWN ((CONTROLLERBUTTONS_T)0x00800000)
#define M_PIf 3.14159265358979323846f
#define M_PI_2f 1.57079632679489661923f // pi/2
#define M_SQRT2f 1.41421356237309504880f
#define M_SQRT1_2f 0.70710678118654752440f /* 1/sqrt(2) */
#ifdef __cplusplus #ifdef __cplusplus
#include <Context.h> #include <Context.h>
#include "Enhancements/savestates.h" #include "Enhancements/savestates.h"

View file

@ -11,7 +11,7 @@
#include "resource/type/Array.h" #include "resource/type/Array.h"
#include "resource/type/Skeleton.h" #include "resource/type/Skeleton.h"
#include "resource/type/PlayerAnimation.h" #include "resource/type/PlayerAnimation.h"
#include <Fast3D/gfx_pc.h> #include <Fast3D/Fast3dWindow.h>
#include <DisplayList.h> #include <DisplayList.h>
extern "C" PlayState* gPlayState; extern "C" PlayState* gPlayState;
@ -292,7 +292,7 @@ extern "C" char* ResourceMgr_LoadPlayerAnimByName(const char* animPath) {
} }
extern "C" void ResourceMgr_PushCurrentDirectory(char* path) { extern "C" void ResourceMgr_PushCurrentDirectory(char* path) {
gfx_push_current_dir(path); Fast::gfx_push_current_dir(path);
} }
extern "C" Gfx* ResourceMgr_LoadGfxByName(const char* path) { extern "C" Gfx* ResourceMgr_LoadGfxByName(const char* path) {

View file

@ -1,5 +1,6 @@
#include "ImGuiUtils.h" #include "ImGuiUtils.h"
#include <Context.h> #include <Context.h>
#include <Window.h>
#include "assets/soh_assets.h" #include "assets/soh_assets.h"
#include "soh/Enhancements/randomizer/rando_hash.h" #include "soh/Enhancements/randomizer/rando_hash.h"

View file

@ -2,7 +2,7 @@
#define MENU_H #define MENU_H
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
#include "graphic/Fast3D/gfx_rendering_api.h" #include "graphic/Fast3D/backends/gfx_rendering_api.h"
#include "MenuTypes.h" #include "MenuTypes.h"
namespace Ship { namespace Ship {

View file

@ -3,7 +3,8 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
#include "soh/SohGui/UIWidgets.hpp" #include "soh/SohGui/UIWidgets.hpp"
#include <graphic/Fast3D/gfx_pc.h> #include <graphic/Fast3D/Fast3dWindow.h>
#include <graphic/Fast3D/interpreter.h>
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "soh/SohGui/SohMenu.h" #include "soh/SohGui/SohMenu.h"
#include "soh/SohGui/SohGui.hpp" #include "soh/SohGui/SohGui.hpp"
@ -86,6 +87,16 @@ static bool disabled_pixelCount;
using namespace UIWidgets; using namespace UIWidgets;
static std::weak_ptr<Fast::Interpreter> mInterpreter;
std::shared_ptr<Fast::Interpreter> GetInterpreter() {
auto intP = mInterpreter.lock();
if (!intP) {
assert(false && "Lost reference to Fast::Interpreter");
}
return intP;
}
void ResolutionCustomWidget(WidgetInfo& info) { void ResolutionCustomWidget(WidgetInfo& info) {
ImGui::BeginDisabled(disabled_everything); ImGui::BeginDisabled(disabled_everything);
// Vertical Resolution // Vertical Resolution
@ -368,18 +379,23 @@ void ResolutionCustomWidget(WidgetInfo& info) {
} }
void RegisterResolutionWidgets() { void RegisterResolutionWidgets() {
auto fastWnd = dynamic_pointer_cast<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow());
mInterpreter = fastWnd->GetInterpreterWeak();
WidgetPath path = { "Settings", "Graphics", SECTION_COLUMN_2 }; WidgetPath path = { "Settings", "Graphics", SECTION_COLUMN_2 };
// Resolution visualiser // Resolution visualiser
mSohMenu->AddWidget(path, "Viewport dimensions: {} x {}", WIDGET_TEXT) mSohMenu->AddWidget(path, "Viewport dimensions: {} x {}", WIDGET_TEXT)
.RaceDisable(false) .RaceDisable(false)
.PreFunc([](WidgetInfo& info) { .PreFunc([](WidgetInfo& info) {
auto gfx_current_game_window_viewport = GetInterpreter().get()->mGameWindowViewport;
info.name = fmt::format("Viewport dimensions: {} x {}", gfx_current_game_window_viewport.width, info.name = fmt::format("Viewport dimensions: {} x {}", gfx_current_game_window_viewport.width,
gfx_current_game_window_viewport.height); gfx_current_game_window_viewport.height);
}); });
mSohMenu->AddWidget(path, "Internal resolution: {} x {}", WIDGET_TEXT) mSohMenu->AddWidget(path, "Internal resolution: {} x {}", WIDGET_TEXT)
.RaceDisable(false) .RaceDisable(false)
.PreFunc([](WidgetInfo& info) { .PreFunc([](WidgetInfo& info) {
auto gfx_current_dimensions = GetInterpreter().get()->mCurDimensions;
info.name = fmt::format("Internal resolution: {} x {}", gfx_current_dimensions.width, info.name = fmt::format("Internal resolution: {} x {}", gfx_current_dimensions.width,
gfx_current_dimensions.height); gfx_current_dimensions.height);
}); });
@ -486,6 +502,7 @@ void RegisterResolutionWidgets() {
} }
} else if (showHorizontalResField) { // Show calculated aspect ratio } else if (showHorizontalResField) { // Show calculated aspect ratio
if (item_aspectRatio) { if (item_aspectRatio) {
auto gfx_current_dimensions = GetInterpreter().get()->mCurDimensions;
ImGui::Dummy({ 0, 2 }); ImGui::Dummy({ 0, 2 });
const float resolvedAspectRatio = const float resolvedAspectRatio =
(float)gfx_current_dimensions.width / gfx_current_dimensions.height; (float)gfx_current_dimensions.width / gfx_current_dimensions.height;
@ -539,6 +556,8 @@ void UpdateResolutionVars() {
short integerScale_maximumBounds = 1; // can change when window is resized short integerScale_maximumBounds = 1; // can change when window is resized
// This is mostly just for UX purposes, as Fit Automatically logic is part of LUS. // This is mostly just for UX purposes, as Fit Automatically logic is part of LUS.
auto gfx_current_game_window_viewport = GetInterpreter().get()->mGameWindowViewport;
auto gfx_current_dimensions = GetInterpreter().get()->mCurDimensions;
if (((float)gfx_current_game_window_viewport.width / gfx_current_game_window_viewport.height) > if (((float)gfx_current_game_window_viewport.width / gfx_current_game_window_viewport.height) >
((float)gfx_current_dimensions.width / gfx_current_dimensions.height)) { ((float)gfx_current_dimensions.width / gfx_current_dimensions.height)) {
// Scale to window height // Scale to window height

View file

@ -11,10 +11,9 @@
#include <imgui.h> #include <imgui.h>
#include <imgui_internal.h> #include <imgui_internal.h>
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
#include <Fast3D/gfx_pc.h>
#ifdef __APPLE__ #ifdef __APPLE__
#include "graphic/Fast3D/gfx_metal.h" #include "graphic/Fast3D/backends/gfx_metal.h"
#endif #endif
#ifdef __SWITCH__ #ifdef __SWITCH__

View file

@ -4,7 +4,7 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
#include "UIWidgets.hpp" #include "UIWidgets.hpp"
#include "Menu.h" #include "Menu.h"
#include "graphic/Fast3D/gfx_rendering_api.h" #include "graphic/Fast3D/backends/gfx_rendering_api.h"
#include "soh/cvar_prefixes.h" #include "soh/cvar_prefixes.h"
#include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/Presets/Presets.h" #include "soh/Enhancements/Presets/Presets.h"
@ -53,9 +53,9 @@ static const std::unordered_map<int32_t, const char*> menuThemeOptions = {
}; };
static const std::unordered_map<int32_t, const char*> textureFilteringMap = { static const std::unordered_map<int32_t, const char*> textureFilteringMap = {
{ FILTER_THREE_POINT, "Three-Point" }, { Fast::FILTER_THREE_POINT, "Three-Point" },
{ FILTER_LINEAR, "Linear" }, { Fast::FILTER_LINEAR, "Linear" },
{ FILTER_NONE, "None" }, { Fast::FILTER_NONE, "None" },
}; };
static const std::unordered_map<int32_t, const char*> logLevels = { static const std::unordered_map<int32_t, const char*> logLevels = {

View file

@ -5,7 +5,7 @@
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
#include "UIWidgets.hpp" #include "UIWidgets.hpp"
#include "include/z64audio.h" #include "include/z64audio.h"
#include "graphic/Fast3D/gfx_rendering_api.h" #include "graphic/Fast3D/backends/gfx_rendering_api.h"
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "soh/SaveManager.h" #include "soh/SaveManager.h"
#include "z64.h" #include "z64.h"

View file

@ -336,8 +336,8 @@ void SohMenu::AddMenuEnhancements() {
.CVar(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding")) .CVar(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"))
.Options(CheckboxOptions().Tooltip( .Options(CheckboxOptions().Tooltip(
"Don't skip cutscenes that are associated with useful glitches. Currently, it is " "Don't skip cutscenes that are associated with useful glitches. Currently, it is "
"only the Fire Temple Darunia CS, Forest Temple Poe Sisters CS, and the Box Skip One " "only the Fire Temple Darunia CS, Forest Temple Poe Sisters CS, Dodongo Boss "
"Point in Jabu.")); "Door Switch CS, Water Temple Dragon Switch CS, and the Box Skip One Point in Jabu."));
AddWidget(path, "Text", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Text", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Skip Pickup Messages", WIDGET_CVAR_CHECKBOX) AddWidget(path, "Skip Pickup Messages", WIDGET_CVAR_CHECKBOX)
@ -373,6 +373,9 @@ void SohMenu::AddMenuEnhancements() {
.CVar(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim")) .CVar(CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"))
.Options(CheckboxOptions().Tooltip("Skips Link's taking breath animation after coming up from water. " .Options(CheckboxOptions().Tooltip("Skips Link's taking breath animation after coming up from water. "
"This setting does not interfere with getting items from underwater.")); "This setting does not interfere with getting items from underwater."));
AddWidget(path, "Empty Bottles Faster", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("FasterBottleEmpty"))
.Options(CheckboxOptions().Tooltip("Speeds up emptying animation when dumping out the contents of a bottle."));
AddWidget(path, "Vine/Ladder Climb Speed +%d", WIDGET_CVAR_SLIDER_INT) AddWidget(path, "Vine/Ladder Climb Speed +%d", WIDGET_CVAR_SLIDER_INT)
.CVar(CVAR_ENHANCEMENT("ClimbSpeed")) .CVar(CVAR_ENHANCEMENT("ClimbSpeed"))
.Options(IntSliderOptions().Min(0).Max(12).DefaultValue(0).Format("+%d")); .Options(IntSliderOptions().Min(0).Max(12).DefaultValue(0).Format("+%d"));
@ -382,6 +385,11 @@ void SohMenu::AddMenuEnhancements() {
AddWidget(path, "Crawl Speed %dx", WIDGET_CVAR_SLIDER_INT) AddWidget(path, "Crawl Speed %dx", WIDGET_CVAR_SLIDER_INT)
.CVar(CVAR_ENHANCEMENT("CrawlSpeed")) .CVar(CVAR_ENHANCEMENT("CrawlSpeed"))
.Options(IntSliderOptions().Min(1).Max(4).DefaultValue(1).Format("%dx")); .Options(IntSliderOptions().Min(1).Max(4).DefaultValue(1).Format("%dx"));
AddWidget(path, "Exclude Glitch-Aiding Crawlspaces", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("GlitchAidingCrawlspaces"))
.PreFunc([](WidgetInfo& info) { info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("CrawlSpeed"), 0) == 1; })
.Options(CheckboxOptions().Tooltip("Don't increase crawl speed when exiting glitch-useful crawlspaces."
"Currently it is only the BOTW crawlspace to locked door"));
AddWidget(path, "King Zora Speed: %.2fx", WIDGET_CVAR_SLIDER_FLOAT) AddWidget(path, "King Zora Speed: %.2fx", WIDGET_CVAR_SLIDER_FLOAT)
.CVar(CVAR_ENHANCEMENT("MweepSpeed")) .CVar(CVAR_ENHANCEMENT("MweepSpeed"))
.Options(FloatSliderOptions().Min(0.1f).Max(5.0f).DefaultValue(1.0f).Format("%.2fx")); .Options(FloatSliderOptions().Min(0.1f).Max(5.0f).DefaultValue(1.0f).Format("%.2fx"));
@ -425,6 +433,10 @@ void SohMenu::AddMenuEnhancements() {
AddWidget(path, "Link as Default File Name", WIDGET_CVAR_CHECKBOX) AddWidget(path, "Link as Default File Name", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("LinkDefaultName")) .CVar(CVAR_ENHANCEMENT("LinkDefaultName"))
.Options(CheckboxOptions().Tooltip("Allows you to have \"Link\" as a premade file name.")); .Options(CheckboxOptions().Tooltip("Allows you to have \"Link\" as a premade file name."));
AddWidget(path, "Spawn Bean Skulltula Faster", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("FasterBeanSkull"))
.Options(CheckboxOptions().Tooltip(
"Makes Gold Skulltulas come out of bean patches faster after bugs dig into center."));
AddWidget(path, "Biggoron Forge Time: %d days", WIDGET_CVAR_SLIDER_INT) AddWidget(path, "Biggoron Forge Time: %d days", WIDGET_CVAR_SLIDER_INT)
.CVar(CVAR_ENHANCEMENT("ForgeTime")) .CVar(CVAR_ENHANCEMENT("ForgeTime"))
.Options(IntSliderOptions().Min(0).Max(3).DefaultValue(3).Format("%d days").Tooltip( .Options(IntSliderOptions().Min(0).Max(3).DefaultValue(3).Format("%d days").Tooltip(

View file

@ -606,9 +606,9 @@ bool Combobox(const char* label, T* value, const std::vector<const char*>& combo
PushStyleCombobox(options.color); PushStyleCombobox(options.color);
const char* longest; const char* longest;
int length = 0; size_t length = 0;
for (auto& string : comboVector) { for (auto& string : comboVector) {
int len = strlen(string); size_t len = strlen(string);
if (len > length) { if (len > length) {
longest = string; longest = string;
length = len; length = len;
@ -690,9 +690,9 @@ bool Combobox(const char* label, T* value, const std::vector<std::string>& combo
PushStyleCombobox(options.color); PushStyleCombobox(options.color);
const char* longest; const char* longest;
int length = 0; size_t length = 0;
for (auto& string : comboVector) { for (auto& string : comboVector) {
int len = string.length(); size_t len = string.length();
if (len > length) { if (len > length) {
longest = string.c_str(); longest = string.c_str();
length = len; length = len;

View file

@ -20,7 +20,7 @@ ResourceFactoryBinaryArrayV0::ReadResource(std::shared_ptr<Ship::File> file,
for (uint32_t i = 0; i < array->ArrayCount; i++) { for (uint32_t i = 0; i < array->ArrayCount; i++) {
if (array->ArrayType == ArrayResourceType::Vertex) { if (array->ArrayType == ArrayResourceType::Vertex) {
// OTRTODO: Implement Vertex arrays as just a vertex resource. // OTRTODO: Implement Vertex arrays as just a vertex resource.
F3DVtx data; Fast::F3DVtx data;
data.v.ob[0] = reader->ReadInt16(); data.v.ob[0] = reader->ReadInt16();
data.v.ob[1] = reader->ReadInt16(); data.v.ob[1] = reader->ReadInt16();
data.v.ob[2] = reader->ReadInt16(); data.v.ob[2] = reader->ReadInt16();

View file

@ -1,6 +1,7 @@
#include "soh/resource/importer/CollisionHeaderFactory.h" #include "soh/resource/importer/CollisionHeaderFactory.h"
#include "soh/resource/type/CollisionHeader.h" #include "soh/resource/type/CollisionHeader.h"
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include <tinyxml2.h>
namespace SOH { namespace SOH {
std::shared_ptr<Ship::IResource> std::shared_ptr<Ship::IResource>

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