Merge remote-tracking branch 'origin/develop-ackbar' into develop922

This commit is contained in:
Demur Rumed 2026-04-14 01:10:10 +00:00
commit a60d46141b
32 changed files with 267 additions and 375 deletions

View file

@ -6,7 +6,7 @@ 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")
project(Ship VERSION 9.2.1 LANGUAGES C CXX) project(Ship VERSION 9.2.2 LANGUAGES C CXX)
include(CMake/soh-cvars.cmake) include(CMake/soh-cvars.cmake)
include(CMake/lus-cvars.cmake) include(CMake/lus-cvars.cmake)
set(SPDLOG_LEVEL_TRACE 0) set(SPDLOG_LEVEL_TRACE 0)

View file

@ -8,8 +8,7 @@ extern "C" {
#include "overlays/actors/ovl_En_Arrow/z_en_arrow.h" #include "overlays/actors/ovl_En_Arrow/z_en_arrow.h"
s32 func_808351D4(Player* thisx, PlayState* play); // Arrow nocked s32 func_808351D4(Player* thisx, PlayState* play); // Arrow nocked
s32 func_808353D8(Player* thisx, PlayState* play); // Aiming in first person void EnArrow_Init(Actor* thisx, PlayState* play);
void Player_InitItemAction(PlayState* play, Player* thisx, PlayerItemAction itemAction);
extern PlayState* gPlayState; extern PlayState* gPlayState;
} }
@ -20,16 +19,6 @@ extern PlayState* gPlayState;
static const s16 sMagicArrowCosts[] = { 4, 4, 8 }; static const s16 sMagicArrowCosts[] = { 4, 4, 8 };
#define MINIGAME_STATUS_ACTIVE 1
static const s16 BUTTON_FLASH_DURATION = 3;
static const s16 BUTTON_FLASH_COUNT = 3;
static const s16 BUTTON_HIGHLIGHT_ALPHA = 128;
static s16 sButtonFlashTimer = 0;
static s16 sButtonFlashCount = 0;
static s16 sJustCycledFrames = 0;
static const PlayerItemAction sArrowCycleOrder[] = { static const PlayerItemAction sArrowCycleOrder[] = {
PLAYER_IA_BOW, PLAYER_IA_BOW,
PLAYER_IA_BOW_FIRE, PLAYER_IA_BOW_FIRE,
@ -54,11 +43,11 @@ static bool HasArrowType(PlayerItemAction itemAction) {
case PLAYER_IA_BOW: case PLAYER_IA_BOW:
return true; return true;
case PLAYER_IA_BOW_FIRE: case PLAYER_IA_BOW_FIRE:
return (INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_ARROW_FIRE); return INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_ARROW_FIRE;
case PLAYER_IA_BOW_ICE: case PLAYER_IA_BOW_ICE:
return (INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE); return INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE;
case PLAYER_IA_BOW_LIGHT: case PLAYER_IA_BOW_LIGHT:
return (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT); return INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT;
default: default:
return false; return false;
} }
@ -77,15 +66,24 @@ static s32 GetBowItemForArrow(PlayerItemAction itemAction) {
} }
} }
static ArrowType GetArrowTypeForArrow(s8 itemAction) {
switch (itemAction) {
case PLAYER_IA_BOW_FIRE:
return ARROW_FIRE;
case PLAYER_IA_BOW_ICE:
return ARROW_ICE;
case PLAYER_IA_BOW_LIGHT:
return ARROW_LIGHT;
default:
return ARROW_NORMAL;
}
}
static bool CanCycleArrows() { static bool CanCycleArrows() {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
// don't allow cycling during minigames return LINK_IS_ADULT && !gSaveContext.minigameState && gPlayState->sceneNum != SCENE_SHOOTING_GALLERY &&
if (gSaveContext.minigameState == MINIGAME_STATUS_ACTIVE) { !(player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && player->rideActor == NULL &&
return false;
}
return !(player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && player->rideActor == NULL &&
INV_CONTENT(SLOT_BOW) == ITEM_BOW && INV_CONTENT(SLOT_BOW) == ITEM_BOW &&
(INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_ARROW_FIRE || INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE || (INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_ARROW_FIRE || INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE ||
INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT); INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT);
@ -113,66 +111,6 @@ static s8 GetNextArrowType(s8 currentArrowType) {
static void UpdateButtonAlpha(s16 flashAlpha, bool isButtonBow, u16* buttonAlpha) { static void UpdateButtonAlpha(s16 flashAlpha, bool isButtonBow, u16* buttonAlpha) {
if (isButtonBow) { if (isButtonBow) {
*buttonAlpha = flashAlpha; *buttonAlpha = flashAlpha;
if (sButtonFlashTimer == 0) {
*buttonAlpha = 255;
}
}
}
static void UpdateFlashEffect(PlayState* play) {
if (sButtonFlashTimer <= 0) {
return;
}
sButtonFlashTimer--;
s16 flashAlpha = (sButtonFlashTimer % 3) ? BUTTON_HIGHLIGHT_ALPHA : 255;
if (sButtonFlashTimer == 0 && sButtonFlashCount < BUTTON_FLASH_COUNT - 1) {
sButtonFlashTimer = BUTTON_FLASH_DURATION;
sButtonFlashCount++;
}
UpdateButtonAlpha(flashAlpha,
(gSaveContext.equips.buttonItems[1] == ITEM_BOW) ||
(gSaveContext.equips.buttonItems[1] >= ITEM_BOW_ARROW_FIRE &&
gSaveContext.equips.buttonItems[1] <= ITEM_BOW_ARROW_LIGHT),
&play->interfaceCtx.cLeftAlpha);
UpdateButtonAlpha(flashAlpha,
(gSaveContext.equips.buttonItems[2] == ITEM_BOW) ||
(gSaveContext.equips.buttonItems[2] >= ITEM_BOW_ARROW_FIRE &&
gSaveContext.equips.buttonItems[2] <= ITEM_BOW_ARROW_LIGHT),
&play->interfaceCtx.cDownAlpha);
UpdateButtonAlpha(flashAlpha,
(gSaveContext.equips.buttonItems[3] == ITEM_BOW) ||
(gSaveContext.equips.buttonItems[3] >= ITEM_BOW_ARROW_FIRE &&
gSaveContext.equips.buttonItems[3] <= ITEM_BOW_ARROW_LIGHT),
&play->interfaceCtx.cRightAlpha);
if (CVarGetInteger(CVAR_ENHANCEMENT("DpadEquips"), 0)) {
UpdateButtonAlpha(flashAlpha,
(gSaveContext.equips.buttonItems[4] == ITEM_BOW) ||
(gSaveContext.equips.buttonItems[4] >= ITEM_BOW_ARROW_FIRE &&
gSaveContext.equips.buttonItems[4] <= ITEM_BOW_ARROW_LIGHT),
&play->interfaceCtx.dpadRightAlpha);
UpdateButtonAlpha(flashAlpha,
(gSaveContext.equips.buttonItems[5] == ITEM_BOW) ||
(gSaveContext.equips.buttonItems[5] >= ITEM_BOW_ARROW_FIRE &&
gSaveContext.equips.buttonItems[5] <= ITEM_BOW_ARROW_LIGHT),
&play->interfaceCtx.dpadLeftAlpha);
UpdateButtonAlpha(flashAlpha,
(gSaveContext.equips.buttonItems[6] == ITEM_BOW) ||
(gSaveContext.equips.buttonItems[6] >= ITEM_BOW_ARROW_FIRE &&
gSaveContext.equips.buttonItems[6] <= ITEM_BOW_ARROW_LIGHT),
&play->interfaceCtx.dpadDownAlpha);
UpdateButtonAlpha(flashAlpha,
(gSaveContext.equips.buttonItems[7] == ITEM_BOW) ||
(gSaveContext.equips.buttonItems[7] >= ITEM_BOW_ARROW_FIRE &&
gSaveContext.equips.buttonItems[7] <= ITEM_BOW_ARROW_LIGHT),
&play->interfaceCtx.dpadUpAlpha);
} }
} }
@ -193,72 +131,53 @@ static void UpdateEquippedBow(PlayState* play, s8 arrowType) {
} }
gSaveContext.buttonStatus[i] = BTN_ENABLED; gSaveContext.buttonStatus[i] = BTN_ENABLED;
sButtonFlashTimer = BUTTON_FLASH_DURATION;
sButtonFlashCount = 0;
} }
} }
UpdateFlashEffect(play);
} }
static void CycleToNextArrow(PlayState* play, Player* player) { bool ArrowCycleMain() {
s8 nextArrow = GetNextArrowType(player->heldItemAction);
if (player->heldActor != NULL && player->heldActor->id == ACTOR_EN_ARROW) {
EnArrow* arrow = (EnArrow*)player->heldActor;
if (arrow->actor.child != NULL) {
Actor_Kill(arrow->actor.child);
}
Actor_Kill(&arrow->actor);
}
Player_InitItemAction(play, player, (PlayerItemAction)nextArrow);
UpdateEquippedBow(play, nextArrow);
Audio_PlaySoundGeneral(NA_SE_PL_CHANGE_ARMS, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
sJustCycledFrames = 2;
}
void ArrowCycleMain() {
if (gPlayState == nullptr || !CanCycleArrows()) { if (gPlayState == nullptr || !CanCycleArrows()) {
return; return false;
} }
if (sJustCycledFrames > 0) {
sJustCycledFrames--;
}
UpdateFlashEffect(gPlayState);
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
Input* input = &gPlayState->state.input[0]; if (player->heldActor != NULL && player->heldActor->id == ACTOR_EN_ARROW) {
if (IsAimingBow(player) && CHECK_BTN_ANY(input->press.button, BTN_R)) {
if (IsHoldingMagicBow(player) && gSaveContext.magicState != MAGIC_STATE_IDLE && player->heldActor == NULL) { if (IsHoldingMagicBow(player) && gSaveContext.magicState != MAGIC_STATE_IDLE && player->heldActor == NULL) {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
return; return true;
} }
// reset magic state to IDLE before cycling to prevent error sound // reset magic state to IDLE before cycling to prevent error sound
gSaveContext.magicState = MAGIC_STATE_IDLE; gSaveContext.magicState = MAGIC_STATE_IDLE;
CycleToNextArrow(gPlayState, player); s8 nextArrow = GetNextArrowType(player->heldItemAction);
player->heldItemAction = nextArrow;
player->itemAction = nextArrow;
Actor* arrow = player->heldActor;
if (arrow->child != NULL) {
Actor_Kill(arrow->child);
arrow->child = NULL;
}
arrow->params = GetArrowTypeForArrow(nextArrow);
EnArrow_Init(arrow, gPlayState);
UpdateEquippedBow(gPlayState, nextArrow);
return true;
} }
return false;
} }
void RegisterArrowCycle() { void RegisterArrowCycle() {
COND_ID_HOOK(OnActorUpdate, ACTOR_PLAYER, CVAR_ARROW_CYCLE_VALUE, [](void* actor) { ArrowCycleMain(); });
// suppress shield input when R is held while aiming to allow arrow cycling // suppress shield input when R is held while aiming to allow arrow cycling
COND_VB_SHOULD(VB_EXECUTE_PLAYER_ACTION_FUNC, CVAR_ARROW_CYCLE_VALUE, { COND_VB_SHOULD(VB_EXECUTE_PLAYER_ACTION_FUNC, CVAR_ARROW_CYCLE_VALUE, {
Player* player = (Player*)va_arg(args, void*); Player* player = (Player*)va_arg(args, void*);
Input* input = (Input*)va_arg(args, void*); Input* input = (Input*)va_arg(args, void*);
if ((IsAimingBow(player) || sJustCycledFrames > 0) && CHECK_BTN_ANY(input->cur.button, BTN_R)) { if (IsAimingBow(player) && CHECK_BTN_ANY(input->press.button, BTN_R)) {
input->cur.button &= ~BTN_R; if (ArrowCycleMain()) {
input->press.button &= ~BTN_R; input->cur.button &= ~BTN_R;
input->press.button &= ~BTN_R;
}
} }
}); });
@ -270,9 +189,9 @@ void RegisterArrowCycle() {
if (gSaveContext.magic < sMagicArrowCosts[magicArrowType]) { if (gSaveContext.magic < sMagicArrowCosts[magicArrowType]) {
*arrowType = ARROW_NORMAL; *arrowType = ARROW_NORMAL;
} else {
*should = false;
} }
*should = false;
}); });
COND_VB_SHOULD(VB_EN_ARROW_MAGIC_CONSUMPTION, CVAR_ARROW_CYCLE_VALUE, { COND_VB_SHOULD(VB_EN_ARROW_MAGIC_CONSUMPTION, CVAR_ARROW_CYCLE_VALUE, {

View file

@ -32,6 +32,7 @@ typedef enum {
static AltTrapType roll = ADD_TRAP_MAX; static AltTrapType roll = ADD_TRAP_MAX;
static int statusTimer = -1; static int statusTimer = -1;
static int eventTimer = -1; static int eventTimer = -1;
static EntranceIndex teleportRoll = ENTR_MAX;
const char* altTrapTypeCvars[] = { const char* altTrapTypeCvars[] = {
CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"), CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"),
@ -41,6 +42,12 @@ const char* altTrapTypeCvars[] = {
CVAR_ENHANCEMENT("ExtraTraps.Kill"), CVAR_ENHANCEMENT("ExtraTraps.Teleport"), CVAR_ENHANCEMENT("ExtraTraps.Kill"), CVAR_ENHANCEMENT("ExtraTraps.Teleport"),
}; };
const std::array<EntranceIndex, 7> teleportDestinations = {
ENTR_LINKS_HOUSE_CHILD_SPAWN, ENTR_SACRED_FOREST_MEADOW_WARP_PAD, ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD,
ENTR_LAKE_HYLIA_WARP_PAD, ENTR_DESERT_COLOSSUS_WARP_PAD, ENTR_GRAVEYARD_WARP_PAD,
ENTR_TEMPLE_OF_TIME_WARP_PAD,
};
std::vector<AltTrapType> getEnabledAddTraps() { std::vector<AltTrapType> getEnabledAddTraps() {
std::vector<AltTrapType> enabledAddTraps; std::vector<AltTrapType> enabledAddTraps;
for (int i = 0; i < ADD_TRAP_MAX; i++) { for (int i = 0; i < ADD_TRAP_MAX; i++) {
@ -102,6 +109,7 @@ static void RollRandomTrap(uint64_t seed) {
break; break;
case ADD_TELEPORT_TRAP: case ADD_TELEPORT_TRAP:
eventTimer = 3; eventTimer = 3;
teleportRoll = ShipUtils::RandomElement(teleportDestinations, &state);
break; break;
default: default:
break; break;
@ -135,32 +143,7 @@ static void OnPlayerUpdate() {
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break; break;
case ADD_TELEPORT_TRAP: { case ADD_TELEPORT_TRAP: {
int entrance; GameInteractor::RawAction::TeleportPlayer(teleportRoll);
int index = Random(0, 7);
switch (index) {
case 0:
entrance = GI_TP_DEST_SERENADE;
break;
case 1:
entrance = GI_TP_DEST_REQUIEM;
break;
case 2:
entrance = GI_TP_DEST_BOLERO;
break;
case 3:
entrance = GI_TP_DEST_MINUET;
break;
case 4:
entrance = GI_TP_DEST_NOCTURNE;
break;
case 5:
entrance = GI_TP_DEST_PRELUDE;
break;
default:
entrance = GI_TP_DEST_LINKSHOUSE;
break;
}
GameInteractor::RawAction::TeleportPlayer(entrance);
break; break;
} }
default: default:

View file

@ -84,7 +84,8 @@ static void DisableFixedCamera_RestoreAllCameraData() {
// Helper to check if a camera type is a fixed camera // Helper to check if a camera type is a fixed camera
static bool IsFixedCameraType(s16 type) { static bool IsFixedCameraType(s16 type) {
return type == CAM_SET_PREREND_FIXED || type == CAM_SET_PREREND_PIVOT || type == CAM_SET_PIVOT_FROM_SIDE; return type == CAM_SET_PREREND_FIXED || type == CAM_SET_PREREND_PIVOT || type == CAM_SET_PIVOT_FROM_SIDE ||
type == CAM_SET_MARKET_BALCONY;
} }
static void RegisterDisableFixedCamera() { static void RegisterDisableFixedCamera() {

View file

@ -1,42 +0,0 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.h"
#include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h"
#include "src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.h"
extern PlayState* gPlayState;
}
#define SKIP_MISC_INTERACTIONS_NAME CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions")
#define SKIP_MISC_INTERACTIONS_VALUE CVarGetInteger(SKIP_MISC_INTERACTIONS_NAME, IS_RANDO)
static void RegisterSkipTimerDelay() {
// Skip Water Temple gate delay
COND_ID_HOOK(OnActorUpdate, ACTOR_BG_SPOT06_OBJECTS, SKIP_MISC_INTERACTIONS_VALUE, [](void* actor) {
auto spot06 = static_cast<BgSpot06Objects*>(actor);
if (spot06->dyna.actor.params == 0) {
spot06->timer = 0;
}
});
// Skip Spirit Sun on Floor activation delay
COND_ID_HOOK(OnActorUpdate, ACTOR_BG_JYA_BOMBCHUIWA, SKIP_MISC_INTERACTIONS_VALUE, [](void* actor) {
auto jya = static_cast<BgJyaBombchuiwa*>(actor);
if (!(jya->drawFlags & 4) && jya->timer > 0 && jya->timer < 9) {
jya->timer = 9;
}
});
// Skip Spirit Sun on Floor & Sun on Block activation delay
COND_ID_HOOK(OnActorUpdate, ACTOR_OBJ_LIGHTSWITCH, SKIP_MISC_INTERACTIONS_VALUE, [](void* actor) {
if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE &&
(gPlayState->roomCtx.curRoom.num == 4 || gPlayState->roomCtx.curRoom.num == 8)) {
auto sun = static_cast<ObjLightswitch*>(actor);
sun->toggleDelay = 0;
}
});
}
static RegisterShipInitFunc initFunc_SkipTimerDelay(RegisterSkipTimerDelay,
{ SKIP_MISC_INTERACTIONS_NAME, "IS_RANDO" });

View file

@ -0,0 +1,18 @@
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h"
extern SaveContext gSaveContext;
}
static void RegisterSpot06GateSkip() {
COND_VB_SHOULD(VB_BG_SPOT06_OBJECTS_GATE_SKIP,
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO), {
BgSpot06Objects* actor = va_arg(args, BgSpot06Objects*);
actor->timer = 0;
*should = false;
});
}
static RegisterShipInitFunc initFunc(RegisterSpot06GateSkip, { CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint") });

View file

@ -109,19 +109,22 @@ void UpdateCurrentBGM(u16 seqKey, SeqType seqType) {
} }
} }
static uint64_t seeded_audio_state = 0;
void RandomizeGroup(SeqType type, bool manual = true) { void RandomizeGroup(SeqType type, bool manual = true) {
std::vector<u16> values; std::vector<u16> values;
uint64_t localRngState = 0;
uint64_t* shuffleState = nullptr;
if (!manual) { if (!manual) {
if (CVarGetInteger(CVAR_AUDIO("RandomizeAudioGenModes"), 0) == RANDOMIZE_ON_FILE_LOAD_SEEDED || int randomizeMode = CVarGetInteger(CVAR_AUDIO("RandomizeAudioGenModes"), 0);
CVarGetInteger(CVAR_AUDIO("RandomizeAudioGenModes"), 0) == RANDOMIZE_ON_RANDO_GEN_ONLY) { if (randomizeMode == RANDOMIZE_ON_FILE_LOAD_SEEDED || randomizeMode == RANDOMIZE_ON_RANDO_GEN_ONLY) {
uint32_t finalSeed = type + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() uint32_t finalSeed = type + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
: static_cast<uint32_t>(gSaveContext.ship.stats.fileCreatedAt)); : static_cast<uint32_t>(gSaveContext.ship.stats.fileCreatedAt));
ShipUtils::RandInit(finalSeed, &seeded_audio_state); ShipUtils::RandInit(finalSeed, &localRngState);
shuffleState = &localRngState;
} }
// For RANDOMIZE_ON_NEW_SCENE, shuffleState remains nullptr, which uses the global RNG
} }
// An empty IncludedSequences set means that the AudioEditor window has never been drawn // An empty IncludedSequences set means that the AudioEditor window has never been drawn
@ -141,7 +144,7 @@ void RandomizeGroup(SeqType type, bool manual = true) {
if (!values.size()) if (!values.size())
return; return;
} }
ShipUtils::Shuffle(values, &seeded_audio_state); ShipUtils::Shuffle(values, shuffleState);
for (const auto& [seqId, seqData] : AudioCollection::Instance->GetAllSequences()) { for (const auto& [seqId, seqData] : AudioCollection::Instance->GetAllSequences()) {
const std::string cvarKey = AudioCollection::Instance->GetCvarKey(seqData.sfxKey); const std::string cvarKey = AudioCollection::Instance->GetCvarKey(seqData.sfxKey);
const std::string cvarLockKey = AudioCollection::Instance->GetCvarLockKey(seqData.sfxKey); const std::string cvarLockKey = AudioCollection::Instance->GetCvarLockKey(seqData.sfxKey);

View file

@ -1889,11 +1889,11 @@ void DrawSillyTab() {
UIWidgets::Separator(true, true, 2.0f, 2.0f); UIWidgets::Separator(true, true, 2.0f, 2.0f);
UIWidgets::CVarCheckbox("Let It Snow", CVAR_GENERAL("LetItSnow"), UIWidgets::CVarCheckbox(
UIWidgets::CheckboxOptions() "Let It Snow", CVAR_GENERAL("LetItSnow"),
.Color(THEME_COLOR) UIWidgets::CheckboxOptions()
.Tooltip("Makes snow fall, changes chest texture colors to red and green, etc, for " .Color(THEME_COLOR)
"December holidays.\nWill reset on restart outside of December 23-25.")); .Tooltip("Makes snow fall for December holidays.\nWill reset on restart outside of December 23-25."));
UIWidgets::Separator(true, true, 2.0f, 2.0f); UIWidgets::Separator(true, true, 2.0f, 2.0f);
@ -2104,24 +2104,28 @@ void ApplySideEffects(CosmeticOption& cosmeticOption) {
} }
} }
static uint64_t seeded_cosmetics_state = 0;
void RandomizeColor(CosmeticOption& cosmeticOption, bool manual = true) { void RandomizeColor(CosmeticOption& cosmeticOption, bool manual = true) {
ImVec4 randomColor; ImVec4 randomColor;
if (!manual && CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), 0) == RANDOMIZE_ON_FILE_LOAD_SEEDED || uint64_t local_seed_state = 0;
!manual && CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), 0) == RANDOMIZE_ON_RANDO_GEN_ONLY) { uint64_t* randomState = nullptr;
uint32_t finalSeed = cosmeticOption.defaultColor.r + cosmeticOption.defaultColor.g + if (!manual) {
cosmeticOption.defaultColor.b + cosmeticOption.defaultColor.a + int randomizeMode = CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), 0);
(IS_RANDO ? Rando::Context::GetInstance()->GetSeed() if (randomizeMode == RANDOMIZE_ON_FILE_LOAD_SEEDED || randomizeMode == RANDOMIZE_ON_RANDO_GEN_ONLY) {
: static_cast<uint32_t>(gSaveContext.ship.stats.fileCreatedAt));
randomColor = GetRandomValue(finalSeed, &seeded_cosmetics_state); uint32_t finalSeed = cosmeticOption.defaultColor.r + cosmeticOption.defaultColor.g +
} else { cosmeticOption.defaultColor.b + cosmeticOption.defaultColor.a +
randomColor = GetRandomValue(); (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
: static_cast<uint32_t>(gSaveContext.ship.stats.fileCreatedAt));
randomState = &local_seed_state;
ShipUtils::RandInit(finalSeed, randomState);
}
// For RANDOMIZE_ON_NEW_SCENE, randomState remains nullptr, which uses the global RNG
} }
randomColor = GetRandomValue(randomState);
Color_RGBA8 newColor; Color_RGBA8 newColor;
newColor.r = static_cast<uint8_t>(randomColor.x * 255.0f); newColor.r = static_cast<uint8_t>(randomColor.x * 255.0f);
newColor.g = static_cast<uint8_t>(randomColor.y * 255.0f); newColor.g = static_cast<uint8_t>(randomColor.y * 255.0f);

View file

@ -52,16 +52,6 @@ typedef enum {
/* 0x08 */ GI_COLOR_BLACK, /* 0x08 */ GI_COLOR_BLACK,
} GIColors; } GIColors;
typedef enum {
/* */ GI_TP_DEST_LINKSHOUSE = ENTR_LINKS_HOUSE_CHILD_SPAWN,
/* */ GI_TP_DEST_MINUET = ENTR_SACRED_FOREST_MEADOW_WARP_PAD,
/* */ GI_TP_DEST_BOLERO = ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD,
/* */ GI_TP_DEST_SERENADE = ENTR_LAKE_HYLIA_WARP_PAD,
/* */ GI_TP_DEST_REQUIEM = ENTR_DESERT_COLOSSUS_WARP_PAD,
/* */ GI_TP_DEST_NOCTURNE = ENTR_GRAVEYARD_WARP_PAD,
/* */ GI_TP_DEST_PRELUDE = ENTR_TEMPLE_OF_TIME_WARP_PAD,
} GITeleportDestinations;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View file

@ -227,6 +227,14 @@ typedef enum {
// - `*BgIceShelter` // - `*BgIceShelter`
VB_BG_ICE_SHELTER_MELT, VB_BG_ICE_SHELTER_MELT,
// #### `result`
// ```c
// this->timer > 0 && this->timer <= 100
// ```
// #### `args`
// - `*BgSpot06Objects`
VB_BG_SPOT06_OBJECTS_GATE_SKIP,
// #### `result` // #### `result`
// ```c // ```c
// gSaveContext.bgsFlag // gSaveContext.bgsFlag
@ -1558,6 +1566,14 @@ typedef enum {
// - `*BossGanondrof` // - `*BossGanondrof`
VB_PHANTOM_GANON_DEATH_SCENE, VB_PHANTOM_GANON_DEATH_SCENE,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - None
VB_PLAY_BEAN_PLANTING_CS,
// #### `result` // #### `result`
// ##### In `DoorWarp1_ChildWarpOut` - `SCENE_DODONGOS_CAVERN_BOSS` // ##### In `DoorWarp1_ChildWarpOut` - `SCENE_DODONGOS_CAVERN_BOSS`
// ```c // ```c

View file

@ -2327,12 +2327,12 @@ void StaticData::HintTable_Init() {
{QM_RED, QM_BLUE, QM_GREEN})); {QM_RED, QM_BLUE, QM_GREEN}));
hintTextTable[RHT_MALON_HINT_OBSTICLE_COURSE] = HintText(CustomMessage("How about trying the #Obstacle Course?# If you beat my time I'll let you keep my favourite #cow# Elsie and her toy #[[1]]#!^" hintTextTable[RHT_MALON_HINT_OBSTICLE_COURSE] = HintText(CustomMessage("How about trying the #Obstacle Course?# If you beat my time I'll let you keep my favourite #cow# Elsie and her toy #[[1]]#!^"
"Challenge the #Obstacle Course?#&\x1B&#Let's go&No thanks#", "Challenge the #Obstacle Course?#\x1B#Let's go&No thanks#",
/*german*/ "Warum versuchst Du Dich nicht mit Epona an dem #Hindernisparcours#?^" /*german*/ "Warum versuchst Du Dich nicht mit Epona an dem #Hindernisparcours#?^"
"Gelingt es Dir den Rekord zu brechen, bekommst Du meine #Lieblingskuh# Elsie^und ihr Lieblingsspielzeug, #[[1]]#!^" "Gelingt es Dir den Rekord zu brechen, bekommst Du meine #Lieblingskuh# Elsie^und ihr Lieblingsspielzeug, #[[1]]#!^"
"Wie sieht's aus?&Möchtest Du es versuchen?\x1B&#Ja!&Nein!#", "Wie sieht's aus?&Möchtest Du es versuchen?\x1B#Ja!&Nein!#",
/*french*/ "Que dirais-tu d'essayer le #Parcours d'Obstacles#? Si tu bats mon temps, je te donnerai ma vache préférée, Elsie, et son jouet #[[1]]#!^" /*french*/ "Que dirais-tu d'essayer le #Parcours d'Obstacles#? Si tu bats mon temps, je te donnerai ma vache préférée, Elsie, et son jouet #[[1]]#!^"
"Tenter le #Parcours d'Obstacles#?&\x1B&#Allons-y&Non merci#", "Tenter le #Parcours d'Obstacles#?\x1B#Allons-y&Non merci#",
{QM_RED, QM_BLUE, QM_GREEN, QM_RED, QM_GREEN})); {QM_RED, QM_BLUE, QM_GREEN, QM_RED, QM_GREEN}));
hintTextTable[RHT_MALON_HINT_TURNING_EVIL] = HintText(CustomMessage("@? Is that you? ^If I ran the ranch, I'd build an #Obstacle Course#, and whoever gets the best time would win a #cow#!^" hintTextTable[RHT_MALON_HINT_TURNING_EVIL] = HintText(CustomMessage("@? Is that you? ^If I ran the ranch, I'd build an #Obstacle Course#, and whoever gets the best time would win a #cow#!^"

View file

@ -36,7 +36,8 @@ void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc, bool mysteriou
itemName = CustomMessage(RAND_GET_OVERRIDE(rc).GetTrickName()); itemName = CustomMessage(RAND_GET_OVERRIDE(rc).GetTrickName());
color = "%g"; color = "%g";
} else { } else {
itemName = CustomMessage(Rando::StaticData::RetrieveItem(rgid).GetName()); const Rando::Item& item = Rando::StaticData::RetrieveItem(rgid);
itemName = item.GetHint().GetHintMessage().GetForCurrentLanguage();
} }
msg.Replace("[[color]]", color); msg.Replace("[[color]]", color);
msg.InsertNames({ itemName, CustomMessage(std::to_string(price)) }); msg.InsertNames({ itemName, CustomMessage(std::to_string(price)) });

View file

@ -140,7 +140,7 @@ void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) {
"et j'aurai quelque chose à te donner! [[color]]([[1]])%w"); "et j'aurai quelque chose à te donner! [[color]]([[1]])%w");
msg.InsertNumber(count); msg.InsertNumber(count);
msg.Replace("[[color]]", item.GetColor()); msg.Replace("[[color]]", item.GetColor());
msg.InsertNames({ item.GetName() }); msg.InsertNames({ item.GetHint().GetHintMessage().GetForCurrentLanguage() });
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;
@ -155,12 +155,10 @@ void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
/*french*/ /*french*/
"Yeaaarrgh! Je suis maudit!^Détruit encore %y100 Araignées de la Malédiction%w " "Yeaaarrgh! Je suis maudit!^Détruit encore %y100 Araignées de la Malédiction%w "
"et j'aurai quelque chose à te donner! [[color]]([[1]])%w"); "et j'aurai quelque chose à te donner! [[color]]([[1]])%w");
msg.Replace("[[color]]", Rando::StaticData::RetrieveItem( Rando::Item& item =
RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet()) Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet());
.GetColor()); msg.Replace("[[color]]", item.GetColor());
msg.InsertNames( msg.InsertNames({ item.GetHint().GetHintMessage().GetForCurrentLanguage() });
{ Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet())
.GetName() });
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;

View file

@ -513,17 +513,13 @@ const HintText Hint::GetItemHintText(uint8_t slot, bool mysterious) const {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
RandomizerCheck hintedCheck = locations[slot]; RandomizerCheck hintedCheck = locations[slot];
RandomizerGet targetRG = ctx->GetItemLocation(hintedCheck)->GetPlacedRandomizerGet(); RandomizerGet targetRG = ctx->GetItemLocation(hintedCheck)->GetPlacedRandomizerGet();
CustomMessage msg;
if (mysterious) { if (mysterious) {
return StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM]; return StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM];
} else if (!ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS) && } else if (targetRG == RG_ICE_TRAP) { // RANDOTODO store in item hint instead of item
targetRG == RG_ICE_TRAP) { // RANDOTODO store in item hint instead of item return HintText(CustomMessage({ ctx->overrides[hintedCheck].GetTrickName() }));
msg = CustomMessage({ ctx->overrides[hintedCheck].GetTrickName() });
} else { } else {
msg = ctx->GetItemLocation(hintedCheck)->GetPlacedItem().GetName(); return ctx->GetItemLocation(hintedCheck)->GetPlacedItem().GetHint();
} }
msg = CustomMessage(ctx->GetItemLocation(hintedCheck)->GetPlacedItem().GetArticle()) + msg;
return HintText(msg);
} }
const HintText Hint::GetAreaHintText(uint8_t slot) const { const HintText Hint::GetAreaHintText(uint8_t slot) const {

View file

@ -13,6 +13,7 @@
#include "soh/SaveManager.h" #include "soh/SaveManager.h"
#include "soh/ShipInit.hpp" #include "soh/ShipInit.hpp"
#include "soh/ObjectExtension/ObjectExtension.h" #include "soh/ObjectExtension/ObjectExtension.h"
#include "item_category_adj.h"
extern "C" { extern "C" {
#include "macros.h" #include "macros.h"
@ -370,6 +371,7 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() {
GetItemID vanillaItem = (GetItemID)Rando::StaticData::RetrieveItem(vanillaRandomizerGet).GetItemID(); GetItemID vanillaItem = (GetItemID)Rando::StaticData::RetrieveItem(vanillaRandomizerGet).GetItemID();
GetItemEntry getItemEntry = GetItemEntry getItemEntry =
Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)vanillaRandomizerGet); Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)vanillaRandomizerGet);
GetItemCategory getItemCategory = Randomizer_AdjustItemCategory(getItemEntry);
if (loc->HasObtained()) { if (loc->HasObtained()) {
SPDLOG_INFO("RC {} already obtained, skipping", static_cast<uint32_t>(rc)); SPDLOG_INFO("RC {} already obtained, skipping", static_cast<uint32_t>(rc));
@ -393,13 +395,8 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() {
// crude fix to ensure map hints are readable. Ideally replace with better hint tracking. // crude fix to ensure map hints are readable. Ideally replace with better hint tracking.
!(getItemEntry.getItemId >= RG_DEKU_TREE_MAP && getItemEntry.getItemId <= RG_ICE_CAVERN_MAP && !(getItemEntry.getItemId >= RG_DEKU_TREE_MAP && getItemEntry.getItemId <= RG_ICE_CAVERN_MAP &&
getItemEntry.modIndex == MOD_RANDOMIZER) && getItemEntry.modIndex == MOD_RANDOMIZER) &&
(getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK || (getItemCategory == ITEM_CATEGORY_JUNK || getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN ||
getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN || getItemCategory == ITEM_CATEGORY_HEALTH || getItemCategory == ITEM_CATEGORY_LESSER))))) {
getItemEntry.getItemCategory == ITEM_CATEGORY_HEALTH ||
getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER ||
// Treat small keys as junk if Skeleton Key is obtained.
(getItemEntry.getItemCategory == ITEM_CATEGORY_SMALL_KEY &&
Flags_GetRandomizerInf(RAND_INF_HAS_SKELETON_KEY))))))) {
Item_DropCollectible(gPlayState, &spawnPos, static_cast<int16_t>(ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000)); Item_DropCollectible(gPlayState, &spawnPos, static_cast<int16_t>(ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000));
} }
} }
@ -446,6 +443,54 @@ void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) {
randomizerQueuedItemEntry = GET_ITEM_NONE; randomizerQueuedItemEntry = GET_ITEM_NONE;
} }
if (receivedItemEntry.modIndex == MOD_RANDOMIZER && receivedItemEntry.getItemId == RG_MAGIC_BEAN_PACK) {
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_PLANTING_BEANS)) {
gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_CRATER].swch |= (1 << 3);
if (gPlayState->sceneNum == SCENE_DEATH_MOUNTAIN_CRATER) {
Flags_SetSwitch(gPlayState, 3);
}
gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_TRAIL].swch |= (1 << 6);
if (gPlayState->sceneNum == SCENE_DEATH_MOUNTAIN_TRAIL) {
Flags_SetSwitch(gPlayState, 6);
}
gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 24);
if (gPlayState->sceneNum == SCENE_DESERT_COLOSSUS) {
Flags_SetSwitch(gPlayState, 24);
}
gSaveContext.sceneFlags[SCENE_GERUDO_VALLEY].swch |= (1 << 3);
if (gPlayState->sceneNum == SCENE_GERUDO_VALLEY) {
Flags_SetSwitch(gPlayState, 3);
}
gSaveContext.sceneFlags[SCENE_GRAVEYARD].swch |= (1 << 3);
if (gPlayState->sceneNum == SCENE_GRAVEYARD) {
Flags_SetSwitch(gPlayState, 3);
}
gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 9);
if (gPlayState->sceneNum == SCENE_KOKIRI_FOREST) {
Flags_SetSwitch(gPlayState, 9);
}
gSaveContext.sceneFlags[SCENE_LAKE_HYLIA].swch |= (1 << 1);
if (gPlayState->sceneNum == SCENE_LAKE_HYLIA) {
Flags_SetSwitch(gPlayState, 1);
}
gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 4) | (1 << 18);
if (gPlayState->sceneNum == SCENE_LOST_WOODS) {
Flags_SetSwitch(gPlayState, 4);
Flags_SetSwitch(gPlayState, 18);
}
gSaveContext.sceneFlags[SCENE_ZORAS_RIVER].swch |= (1 << 3);
if (gPlayState->sceneNum == SCENE_ZORAS_RIVER) {
Flags_SetSwitch(gPlayState, 3);
}
ObjBean* bean = (ObjBean*)Actor_Find(&gPlayState->actorCtx, ACTOR_OBJ_BEAN, ACTORCAT_BG);
if (bean != nullptr) {
Flags_SetSwitch(gPlayState, bean->dyna.actor.params & 0x3F);
func_80B8FE00(bean);
}
AMMO(ITEM_BEAN) = 0;
}
}
if (receivedItemEntry.modIndex == MOD_NONE && if (receivedItemEntry.modIndex == MOD_NONE &&
(receivedItemEntry.itemId == ITEM_HEART_PIECE || receivedItemEntry.itemId == ITEM_HEART_PIECE_2 || (receivedItemEntry.itemId == ITEM_HEART_PIECE || receivedItemEntry.itemId == ITEM_HEART_PIECE_2 ||
receivedItemEntry.itemId == ITEM_HEART_CONTAINER)) { receivedItemEntry.itemId == ITEM_HEART_CONTAINER)) {

View file

@ -1,7 +1,6 @@
#include "soh_assets.h" #include "soh_assets.h"
#include "static_data.h" #include "static_data.h"
#include "SeedContext.h" #include "SeedContext.h"
#include "logic.h"
#include "textures/icon_item_24_static/icon_item_24_static.h" #include "textures/icon_item_24_static/icon_item_24_static.h"
#include "textures/icon_item_static/icon_item_static.h" #include "textures/icon_item_static/icon_item_static.h"
#include "z64object.h" #include "z64object.h"

View file

@ -496,7 +496,8 @@ void RegionTable_Init_GanonsCastle() {
areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_OPEN_DOOR] = Region("Ganon's Castle MQ Fire Trial Open Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_OPEN_DOOR] = Region("Ganon's Castle MQ Fire Trial Open Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, {
//Exits //Exits
ENTRANCE(RR_GANONS_CASTLE_MQ_MAIN, true) ENTRANCE(RR_GANONS_CASTLE_MQ_MAIN, true),
ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_OPEN, true),
}); });
areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_OPEN] = Region("Ganon's Castle MQ Fire Trial From Open Door", SCENE_INSIDE_GANONS_CASTLE, { areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_OPEN] = Region("Ganon's Castle MQ Fire Trial From Open Door", SCENE_INSIDE_GANONS_CASTLE, {
@ -511,7 +512,7 @@ void RegionTable_Init_GanonsCastle() {
areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_BARRED] = Region("Ganon's Castle MQ Fire Trial From Barred Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_BARRED] = Region("Ganon's Castle MQ Fire Trial From Barred Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, {
//Exits //Exits
ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR, true) ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR, true),
}); });
areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR] = Region("Ganon's Castle MQ Fire Trial Barred Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR] = Region("Ganon's Castle MQ Fire Trial Barred Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, {

View file

@ -30,17 +30,17 @@ void RegionTable_Init_DeathMountainCrater() {
ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)),
ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 16 || logic->Hearts() >= 3), ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 16 || logic->Hearts() >= 3),
ENTRANCE(RR_DMC_BLOCKED_EXIT, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->DMCUpperToPots()) || ENTRANCE(RR_DMC_BLOCKED_EXIT, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->DMCUpperToPots()) ||
(logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->ReachDistantScarecrow() && logic->TakeDamage())), (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))),
ENTRANCE(RR_DMC_POTS, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || ENTRANCE(RR_DMC_POTS, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) ||
(logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))),
ENTRANCE(RR_DMC_POT_GROTTO_EXIT, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || ENTRANCE(RR_DMC_POT_GROTTO_EXIT, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) ||
(logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))),
ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) ||
(logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))),
ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) ||
(logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->TakeDamage()), (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)),
ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) ||
(logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))),
}); });
areaTable[RR_DMC_ROCKS_GROTTO_ENTRY] = Region("DMC Rocks Grotto Entry", SCENE_DEATH_MOUNTAIN_CRATER, { areaTable[RR_DMC_ROCKS_GROTTO_ENTRY] = Region("DMC Rocks Grotto Entry", SCENE_DEATH_MOUNTAIN_CRATER, {
@ -56,17 +56,17 @@ void RegionTable_Init_DeathMountainCrater() {
ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)),
ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 16 || logic->Hearts() >= 3), ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 16 || logic->Hearts() >= 3),
ENTRANCE(RR_DMC_BLOCKED_EXIT, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || ENTRANCE(RR_DMC_BLOCKED_EXIT, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) ||
(logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))),
ENTRANCE(RR_DMC_POTS, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || ENTRANCE(RR_DMC_POTS, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) ||
(logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->ReachDistantScarecrow() && logic->TakeDamage())), (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))),
ENTRANCE(RR_DMC_POT_GROTTO_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCUpperToPots()) || ENTRANCE(RR_DMC_POT_GROTTO_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCUpperToPots()) ||
(logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->ReachDistantScarecrow() && logic->TakeDamage())), (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))),
ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) ||
(logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow() && logic->TakeDamage())), (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))),
ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) ||
(logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->TakeDamage()), (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)),
ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) ||
(logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow() && logic->TakeDamage())), (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))),
}); });
areaTable[RR_DMC_BLOCKED_ENTRY] = Region("DMC Blocked Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { areaTable[RR_DMC_BLOCKED_ENTRY] = Region("DMC Blocked Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, {
@ -92,13 +92,13 @@ void RegionTable_Init_DeathMountainCrater() {
ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2), ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2),
ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 16 || logic->Hearts() >= 3), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 16 || logic->Hearts() >= 3),
ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) ||
(logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && logic->CanClimbLadder())), (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder())),
ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) ||
((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && logic->CanClimbLadder()) || ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder()) ||
(logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) ||
((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS))), ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS))),
ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad()) || ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad()) ||
(logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->ReachDistantScarecrow() && logic->CanClimbLadder())),
}); });
areaTable[RR_DMC_POTS_ENTRY] = Region("DMC Pots Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { areaTable[RR_DMC_POTS_ENTRY] = Region("DMC Pots Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, {
@ -124,11 +124,11 @@ void RegionTable_Init_DeathMountainCrater() {
ENTRANCE(RR_DMC_POTS, true), ENTRANCE(RR_DMC_POTS, true),
ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 8 || logic->Hearts() >= 2), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 8 || logic->Hearts() >= 2),
ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad()) || ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad()) ||
(logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->ReachDistantScarecrow() && logic->CanClimbLadder())),
ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) ||
((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && logic->CanClimbLadder())), ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder())),
ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) ||
(logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->ReachDistantScarecrow() && logic->CanClimbLadder())),
}); });
areaTable[RR_DMC_POT_GROTTO_ENTRY] = Region("DMC Pot Grotto Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { areaTable[RR_DMC_POT_GROTTO_ENTRY] = Region("DMC Pot Grotto Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, {
@ -154,11 +154,11 @@ void RegionTable_Init_DeathMountainCrater() {
ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2), ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2),
ENTRANCE(RR_DMC_POT_GROTTO_EXIT, true), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, true),
ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad()) || ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad()) ||
(logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->ReachDistantScarecrow() && logic->CanClimbLadder())),
ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) ||
((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->TakeDamage() && logic->CanClimbLadder())), ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder())),
ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) ||
(logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->ReachDistantScarecrow() && logic->CanClimbLadder())),
}); });
areaTable[RR_DMC_PAD_ENTRY] = Region("DMC Pad Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { areaTable[RR_DMC_PAD_ENTRY] = Region("DMC Pad Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, {
@ -188,7 +188,7 @@ void RegionTable_Init_DeathMountainCrater() {
ENTRANCE(RR_DMC_POT_GROTTO_EXIT, (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->DMCPadToPots() || ENTRANCE(RR_DMC_POT_GROTTO_EXIT, (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->DMCPadToPots() ||
((logic->IsAdult && logic->FireTimer() >= 24 || logic->Hearts() >= 5) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), ((logic->IsAdult && logic->FireTimer() >= 24 || logic->Hearts() >= 5) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))),
ENTRANCE(RR_DMC_CENTRAL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), ENTRANCE(RR_DMC_CENTRAL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)),
ENTRANCE(RR_DMC_FAR_PLATFORM, ((logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->CanClimbLadder() && logic->DMCPadToPots()) || ENTRANCE(RR_DMC_FAR_PLATFORM, ((logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder() && logic->DMCPadToPots()) ||
((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) ||
(logic->IsAdult && (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))|| (logic->IsAdult && (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))||
(logic->IsAdult && (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow())), (logic->IsAdult && (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow())),
@ -232,7 +232,7 @@ void RegionTable_Init_DeathMountainCrater() {
(logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))),
ENTRANCE(RR_DMC_CENTRAL, logic->HasItem(RG_CLIMB) && (logic->FireTimer() >= 48 || logic->Hearts() >= 9)), ENTRANCE(RR_DMC_CENTRAL, logic->HasItem(RG_CLIMB) && (logic->FireTimer() >= 48 || logic->Hearts() >= 9)),
ENTRANCE(RR_DMC_FAR_PLATFORM, logic->HasItem(RG_CLIMB) && ENTRANCE(RR_DMC_FAR_PLATFORM, logic->HasItem(RG_CLIMB) &&
(((logic->FireTimer() >= 88 || logic->Hearts() >= 3) && logic->TakeDamage() && logic->CanClimbLadder() && logic->DMCPadToPots()) || (((logic->FireTimer() >= 88 || logic->Hearts() >= 3) && logic->TakeDamage() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanClimbLadder() && logic->DMCPadToPots()) ||
((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || ((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) ||
(logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))|| (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))||
(logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow()))), (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow()))),

View file

@ -4555,51 +4555,6 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
if (INV_CONTENT(ITEM_BEAN) == ITEM_NONE) { if (INV_CONTENT(ITEM_BEAN) == ITEM_NONE) {
INV_CONTENT(ITEM_BEAN) = ITEM_BEAN; INV_CONTENT(ITEM_BEAN) = ITEM_BEAN;
AMMO(ITEM_BEAN) = 10; AMMO(ITEM_BEAN) = 10;
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_PLANTING_BEANS)) {
gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_CRATER].swch |= (1 << 3);
if (gPlayState->sceneNum == SCENE_DEATH_MOUNTAIN_CRATER) {
Flags_SetSwitch(gPlayState, 3);
}
gSaveContext.sceneFlags[SCENE_DEATH_MOUNTAIN_TRAIL].swch |= (1 << 6);
if (gPlayState->sceneNum == SCENE_DEATH_MOUNTAIN_TRAIL) {
Flags_SetSwitch(gPlayState, 6);
}
gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 24);
if (gPlayState->sceneNum == SCENE_DESERT_COLOSSUS) {
Flags_SetSwitch(gPlayState, 24);
}
gSaveContext.sceneFlags[SCENE_GERUDO_VALLEY].swch |= (1 << 3);
if (gPlayState->sceneNum == SCENE_GERUDO_VALLEY) {
Flags_SetSwitch(gPlayState, 3);
}
gSaveContext.sceneFlags[SCENE_GRAVEYARD].swch |= (1 << 3);
if (gPlayState->sceneNum == SCENE_GRAVEYARD) {
Flags_SetSwitch(gPlayState, 3);
}
gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 9);
if (gPlayState->sceneNum == SCENE_KOKIRI_FOREST) {
Flags_SetSwitch(gPlayState, 9);
}
gSaveContext.sceneFlags[SCENE_LAKE_HYLIA].swch |= (1 << 1);
if (gPlayState->sceneNum == SCENE_LAKE_HYLIA) {
Flags_SetSwitch(gPlayState, 1);
}
gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 4) | (1 << 18);
if (gPlayState->sceneNum == SCENE_LOST_WOODS) {
Flags_SetSwitch(gPlayState, 4);
Flags_SetSwitch(gPlayState, 18);
}
gSaveContext.sceneFlags[SCENE_ZORAS_RIVER].swch |= (1 << 3);
if (gPlayState->sceneNum == SCENE_ZORAS_RIVER) {
Flags_SetSwitch(gPlayState, 3);
}
ObjBean* bean = (ObjBean*)Actor_Find(&gPlayState->actorCtx, ACTOR_OBJ_BEAN, ACTORCAT_BG);
if (bean != nullptr) {
Flags_SetSwitch(gPlayState, bean->dyna.actor.params & 0x3F);
func_80B8FE00(bean);
}
AMMO(ITEM_BEAN) = 0;
}
} }
break; break;
case RG_DOUBLE_DEFENSE: case RG_DOUBLE_DEFENSE:

View file

@ -24,11 +24,14 @@ extern "C" {
#include "src/overlays/actors/ovl_En_Jj/z_en_jj.h" #include "src/overlays/actors/ovl_En_Jj/z_en_jj.h"
#include "src/overlays/actors/ovl_En_Daiku/z_en_daiku.h" #include "src/overlays/actors/ovl_En_Daiku/z_en_daiku.h"
#include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" #include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h"
#include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h"
#include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h" #include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h"
#include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" #include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h"
#include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h" #include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h"
#include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h" #include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h"
#include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h" #include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h"
#include "src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.h"
#include "src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.h"
#include <overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h> #include <overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h>
#include <overlays/actors/ovl_En_Ik/z_en_ik.h> #include <overlays/actors/ovl_En_Ik/z_en_ik.h>
#include <objects/object_gnd/object_gnd.h> #include <objects/object_gnd/object_gnd.h>
@ -328,6 +331,15 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
RateLimitedSuccessChime(); RateLimitedSuccessChime();
break; break;
} }
case ACTOR_BG_JYA_BOMBCHUIWA: {
BgJyaBombchuiwa* bombchuiwa = (BgJyaBombchuiwa*)actor;
if (!(bombchuiwa->drawFlags & 4) && bombchuiwa->timer >= 0 && bombchuiwa->timer < 9) {
bombchuiwa->timer = 9;
}
*should = false;
RateLimitedSuccessChime();
break;
}
case ACTOR_EN_GO2: { case ACTOR_EN_GO2: {
EnGo2* biggoron = (EnGo2*)actor; EnGo2* biggoron = (EnGo2*)actor;
biggoron->isAwake = true; biggoron->isAwake = true;
@ -376,8 +388,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
RateLimitedSuccessChime(); RateLimitedSuccessChime();
break; break;
} }
case ACTOR_OBJ_LIGHTSWITCH: {
ObjLightswitch* lightswitch = (ObjLightswitch*)actor;
lightswitch->toggleDelay = 0;
*should = false;
RateLimitedSuccessChime();
break;
}
case ACTOR_BG_ICE_SHUTTER: case ACTOR_BG_ICE_SHUTTER:
case ACTOR_OBJ_LIGHTSWITCH:
case ACTOR_OBJ_SYOKUDAI: case ACTOR_OBJ_SYOKUDAI:
case ACTOR_OBJ_TIMEBLOCK: case ACTOR_OBJ_TIMEBLOCK:
case ACTOR_EN_PO_SISTERS: case ACTOR_EN_PO_SISTERS:
@ -554,6 +572,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
} }
break; break;
} }
case VB_PLAY_BEAN_PLANTING_CS:
case VB_PLAY_EYEDROP_CREATION_ANIM: case VB_PLAY_EYEDROP_CREATION_ANIM:
case VB_PLAY_EYEDROPS_CS: case VB_PLAY_EYEDROPS_CS:
case VB_PLAY_DROP_FISH_FOR_JABU_CS: case VB_PLAY_DROP_FISH_FOR_JABU_CS:

View file

@ -5,8 +5,7 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <spdlog/fmt/fmt.h> #include <spdlog/fmt/fmt.h>
#include <regex> #include "soh/ShipInit.hpp"
#include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include <z64.h> #include <z64.h>
@ -625,37 +624,37 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) {
case kEffectTpLinksHouse: case kEffectTpLinksHouse:
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>(); effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] = dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
GI_TP_DEST_LINKSHOUSE; ENTR_LINKS_HOUSE_CHILD_SPAWN;
break; break;
case kEffectTpMinuet: case kEffectTpMinuet:
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>(); effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] = dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
GI_TP_DEST_MINUET; ENTR_SACRED_FOREST_MEADOW_WARP_PAD;
break; break;
case kEffectTpBolero: case kEffectTpBolero:
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>(); effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] = dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
GI_TP_DEST_BOLERO; ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD;
break; break;
case kEffectTpSerenade: case kEffectTpSerenade:
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>(); effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] = dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
GI_TP_DEST_SERENADE; ENTR_LAKE_HYLIA_WARP_PAD;
break; break;
case kEffectTpRequiem: case kEffectTpRequiem:
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>(); effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] = dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
GI_TP_DEST_REQUIEM; ENTR_DESERT_COLOSSUS_WARP_PAD;
break; break;
case kEffectTpNocturne: case kEffectTpNocturne:
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>(); effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] = dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
GI_TP_DEST_NOCTURNE; ENTR_GRAVEYARD_WARP_PAD;
break; break;
case kEffectTpPrelude: case kEffectTpPrelude:
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>(); effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] = dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
GI_TP_DEST_PRELUDE; ENTR_TEMPLE_OF_TIME_WARP_PAD;
break; break;
default: default:

View file

@ -405,7 +405,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
std::vector<std::string> args; std::vector<std::string> args;
if (argc > 1) { if (argc > 1) {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
args.push_back(argv[argc]); args.push_back(argv[i]);
} }
} }
Extractor extract; Extractor extract;
@ -464,7 +464,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
#elif (defined(__WIIU__) || defined(__SWITCH__)) #elif (defined(__WIIU__) || defined(__SWITCH__))
extractStep = ES_VERIFY; extractStep = ES_VERIFY;
#else #else
extractStep = ES_EXTRACT; extractStep = args.empty() ? ES_EXTRACT : ES_EXTRACT_ARGS;
#endif #endif
} else { } else {
std::string msg; std::string msg;
@ -549,11 +549,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
"OK", "", [&]() { exit(0); }); "OK", "", [&]() { exit(0); });
} else { } else {
windowsStep = WS_DONE; windowsStep = WS_DONE;
if (args.size() > 0) { extractStep = args.empty() ? ES_EXTRACT : ES_EXTRACT_ARGS;
extractStep = ES_EXTRACT_ARGS;
} else {
extractStep = ES_EXTRACT;
}
} }
continue; continue;
} }
@ -564,7 +560,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
} }
case ES_EXTRACT_ARGS: { case ES_EXTRACT_ARGS: {
#if !defined(__SWITCH__) && !defined(__WIIU__) #if !defined(__SWITCH__) && !defined(__WIIU__)
if (args.size() == 0) { if (args.empty()) {
SohGui::RegisterPopup( SohGui::RegisterPopup(
"Run Ship of Harkinian", "All files have been processed. Run SoH?", "Yes", "No", "Run Ship of Harkinian", "All files have been processed. Run SoH?", "Yes", "No",
[&]() { [&]() {

View file

@ -1806,7 +1806,7 @@ void SohMenu::AddMenuEnhancements() {
.CVar(CVAR_CHEAT("SpeedModifier.DoesntChangeJump")); .CVar(CVAR_CHEAT("SpeedModifier.DoesntChangeJump"));
AddWidget(path, "Multiplier:", WIDGET_CVAR_SLIDER_FLOAT) AddWidget(path, "Multiplier:", WIDGET_CVAR_SLIDER_FLOAT)
.CVar(CVAR_CHEAT("SpeedModifier.Value")) .CVar(CVAR_CHEAT("SpeedModifier.Value"))
.Options(FloatSliderOptions().IsPercentage().Min(1.0f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true).Format( .Options(FloatSliderOptions().IsPercentage().Min(0.01f).Max(5.0f).DefaultValue(1.0f).ShowButtons(true).Format(
"%.0f%%")); "%.0f%%"));
AddWidget(path, "Button Combination:", WIDGET_CVAR_BTN_SELECTOR) AddWidget(path, "Button Combination:", WIDGET_CVAR_BTN_SELECTOR)
.CVar(CVAR_CHEAT("SpeedModifier.Btn")) .CVar(CVAR_CHEAT("SpeedModifier.Btn"))

View file

@ -1255,16 +1255,7 @@ bool CVarBtnSelector(const char* label, const char* cvarName, const BtnSelectorO
} }
} // namespace UIWidgets } // namespace UIWidgets
ImVec4 GetRandomValue() { ImVec4 GetRandomValue(uint64_t* state) {
ImVec4 NewColor;
NewColor.x = (float)ShipUtils::RandomDouble();
NewColor.y = (float)ShipUtils::RandomDouble();
NewColor.z = (float)ShipUtils::RandomDouble();
return NewColor;
}
ImVec4 GetRandomValue(uint32_t seed, uint64_t* state) {
ShipUtils::RandInit(seed, state);
ImVec4 NewColor; ImVec4 NewColor;
NewColor.x = (float)ShipUtils::RandomDouble(state); NewColor.x = (float)ShipUtils::RandomDouble(state);
NewColor.y = (float)ShipUtils::RandomDouble(state); NewColor.y = (float)ShipUtils::RandomDouble(state);

View file

@ -1089,8 +1089,7 @@ void InsertHelpHoverText(const std::string& text);
void InsertHelpHoverText(const char* text); void InsertHelpHoverText(const char* text);
} // namespace UIWidgets } // namespace UIWidgets
ImVec4 GetRandomValue(); ImVec4 GetRandomValue(uint64_t* state = nullptr);
ImVec4 GetRandomValue(uint32_t seed, uint64_t* state = nullptr);
Color_RGBA8 RGBA8FromVec(ImVec4 vec); Color_RGBA8 RGBA8FromVec(ImVec4 vec);
ImVec4 VecFromRGBA8(Color_RGBA8 color); ImVec4 VecFromRGBA8(Color_RGBA8 color);

View file

@ -7,6 +7,7 @@
#include "z_bg_spot06_objects.h" #include "z_bg_spot06_objects.h"
#include "objects/object_spot06_objects/object_spot06_objects.h" #include "objects/object_spot06_objects/object_spot06_objects.h"
#include "soh/Enhancements/custom-message/CustomMessageTypes.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_HOOKSHOT_PULLS_ACTOR #define FLAGS ACTOR_FLAG_HOOKSHOT_PULLS_ACTOR
@ -266,7 +267,7 @@ void BgSpot06Objects_GateWaitForSwitch(BgSpot06Objects* this, PlayState* play) {
* This is where the gate waits a few frames before rising after the switch is set. * This is where the gate waits a few frames before rising after the switch is set.
*/ */
void BgSpot06Objects_GateWaitToOpen(BgSpot06Objects* this, PlayState* play) { void BgSpot06Objects_GateWaitToOpen(BgSpot06Objects* this, PlayState* play) {
if (this->timer != 0) { if (GameInteractor_Should(VB_BG_SPOT06_OBJECTS_GATE_SKIP, this->timer != 0, this)) {
this->timer--; this->timer--;
} }
@ -604,7 +605,7 @@ void BgSpot06Objects_WaterPlaneCutsceneRise(BgSpot06Objects* this, PlayState* pl
play->roomCtx.unk_74[0] = 0; // Apply the moving under water texture to lake hylia ground play->roomCtx.unk_74[0] = 0; // Apply the moving under water texture to lake hylia ground
} }
} else { } else {
Math_SmoothStepToF(&this->lakeHyliaWaterLevel, 1.0f, 0.1f, 1.0f, 0.001f); Math_SmoothStepToF(&this->lakeHyliaWaterLevel, 1.0f, 0.1f, IS_RANDO ? 10.0f : 1.0f, 0.001f);
play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_LOWERED; play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_LOWERED;
play->colCtx.colHeader->waterBoxes[LHWB_MAIN_1].ySurface = this->dyna.actor.world.pos.y; play->colCtx.colHeader->waterBoxes[LHWB_MAIN_1].ySurface = this->dyna.actor.world.pos.y;
play->colCtx.colHeader->waterBoxes[LHWB_MAIN_2].ySurface = this->dyna.actor.world.pos.y; play->colCtx.colHeader->waterBoxes[LHWB_MAIN_2].ySurface = this->dyna.actor.world.pos.y;
@ -634,7 +635,7 @@ void BgSpot06Objects_WaterPlaneCutsceneLower(BgSpot06Objects* this, PlayState* p
this->actionFunc = BgSpot06Objects_DoNothing; this->actionFunc = BgSpot06Objects_DoNothing;
} else { } else {
// Go slightly beyond -681 so the smoothing doesn't slow down too much (matches the reverse of water rise func) // Go slightly beyond -681 so the smoothing doesn't slow down too much (matches the reverse of water rise func)
Math_SmoothStepToF(&this->lakeHyliaWaterLevel, -682.0f, 0.1f, 1.0f, 0.001f); Math_SmoothStepToF(&this->lakeHyliaWaterLevel, -682.0f, 0.1f, 10.0f, 0.01f);
play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_LOWERED; play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_LOWERED;
play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z - 50; play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z - 50;
play->colCtx.colHeader->waterBoxes[LHWB_MAIN_1].ySurface = yPos; play->colCtx.colHeader->waterBoxes[LHWB_MAIN_1].ySurface = yPos;

View file

@ -4246,7 +4246,7 @@ void BossTw_BlastIce(BossTw* this, PlayState* play) {
Math_ApproachF(&sKotakePtr->workf[UNK_F9], 80.0f, 1.0f, 3.0f); Math_ApproachF(&sKotakePtr->workf[UNK_F9], 80.0f, 1.0f, 3.0f);
Math_ApproachF(&sKotakePtr->workf[UNK_F11], 255.0f, 1.0f, 10.0f); Math_ApproachF(&sKotakePtr->workf[UNK_F11], 255.0f, 1.0f, 10.0f);
Math_ApproachF(&sKotakePtr->workf[UNK_F12], 0.04f, 0.1f, 0.002f); Math_ApproachF(&sKotakePtr->workf[UNK_F12], 0.04f, 0.1f, 0.002f);
Math_ApproachF(&sKotakePtr->workf[UNK_F16], 70.0f, 1.0f, 5.0f); Math_ApproachF(&sKotakePtr->workf[UNK_F16], 70.0f, 1.0f, -5.0f);
if ((this->timers[0] == 70) || (this->timers[0] == 30)) { if ((this->timers[0] == 70) || (this->timers[0] == 30)) {
sKotakePtr->workf[UNK_F16] = 10.0f; sKotakePtr->workf[UNK_F16] = 10.0f;
@ -5037,9 +5037,8 @@ void BossTw_DrawEffects(PlayState* play) {
if (sp18F == 0) { if (sp18F == 0) {
gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(gTwinrovaIceSurroundingPlayerMaterialDL)); gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(gTwinrovaIceSurroundingPlayerMaterialDL));
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, 255); gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, 255);
gSPSegment( gSPSegment(POLY_XLU_DISP++, 8,
POLY_XLU_DISP++, 8, Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, 0, 0, 0x20, 0x20));
Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, 0, 0, 0x20, 0x20, 0, 0, 0, 0));
sp18F++; sp18F++;
BossTw_InitRand(1, 0x71AC, 0x263A); BossTw_InitRand(1, 0x71AC, 0x263A);
} }
@ -5091,9 +5090,8 @@ void BossTw_DrawEffects(PlayState* play) {
} }
gSPSegment(POLY_XLU_DISP++, 8, gSPSegment(POLY_XLU_DISP++, 8,
Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, (currentEffect->frame * 3) & 0x7F, Gfx_TwoTexScroll(play->state.gfxCtx, 0, (currentEffect->frame * 3) & 0x7F,
(-currentEffect->frame * 15) & 0xFF, 0x20, 0x40, 1, 0, 0, 0x20, 0x20, 3, -15, (-currentEffect->frame * 15) & 0xFF, 0x20, 0x40, 1, 0, 0, 0x20, 0x20));
0, 0));
Matrix_Translate(currentEffect->pos.x, currentEffect->pos.y, currentEffect->pos.z, MTXMODE_NEW); Matrix_Translate(currentEffect->pos.x, currentEffect->pos.y, currentEffect->pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&play->billboardMtxF); Matrix_ReplaceRotation(&play->billboardMtxF);
Matrix_Scale(currentEffect->workf[EFF_SCALE], currentEffect->workf[EFF_SCALE], 1.0f, MTXMODE_APPLY); Matrix_Scale(currentEffect->workf[EFF_SCALE], currentEffect->workf[EFF_SCALE], 1.0f, MTXMODE_APPLY);

View file

@ -2,7 +2,6 @@
#include "objects/object_fz/object_fz.h" #include "objects/object_fz/object_fz.h"
#include "soh/frame_interpolation.h" #include "soh/frame_interpolation.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ObjectExtension/ActorMaximumHealth.h"
#define FLAGS \ #define FLAGS \
(ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \ (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \
@ -887,8 +886,8 @@ void EnFz_DrawIceSmoke(EnFz* this, PlayState* play) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, iceSmoke->primAlpha); gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, iceSmoke->primAlpha);
gSPSegment(POLY_XLU_DISP++, 0x08, gSPSegment(POLY_XLU_DISP++, 0x08,
Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, 3 * (iceSmoke->timer + (3 * i)), Gfx_TwoTexScroll(play->state.gfxCtx, 0, 3 * (iceSmoke->timer + (3 * i)),
15 * (iceSmoke->timer + (3 * i)), 32, 64, 1, 0, 0, 32, 32, 3, 15, 0, 0)); 15 * (iceSmoke->timer + (3 * i)), 32, 64, 1, 0, 0, 32, 32));
Matrix_Translate(iceSmoke->pos.x, iceSmoke->pos.y, iceSmoke->pos.z, MTXMODE_NEW); Matrix_Translate(iceSmoke->pos.x, iceSmoke->pos.y, iceSmoke->pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&play->billboardMtxF); Matrix_ReplaceRotation(&play->billboardMtxF);
Matrix_Scale(iceSmoke->xyScale, iceSmoke->xyScale, 1.0f, MTXMODE_APPLY); Matrix_Scale(iceSmoke->xyScale, iceSmoke->xyScale, 1.0f, MTXMODE_APPLY);

View file

@ -551,7 +551,9 @@ void ObjBean_WaitForBean(ObjBean* this, PlayState* play) {
void func_80B8FE00(ObjBean* this) { void func_80B8FE00(ObjBean* this) {
this->actionFunc = func_80B8FE3C; this->actionFunc = func_80B8FE3C;
ObjBean_SetDrawMode(this, BEAN_STATE_DRAW_LEAVES); ObjBean_SetDrawMode(this, BEAN_STATE_DRAW_LEAVES);
this->timer = 60; if (GameInteractor_Should(VB_PLAY_BEAN_PLANTING_CS, true)) {
this->timer = 60;
}
} }
// Link is looking at the soft soil // Link is looking at the soft soil

View file

@ -256,9 +256,8 @@ void ObjSwitch_SetOn(ObjSwitch* this, PlayState* play) {
} else { } else {
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
} }
this->cooldownOn = true;
} }
this->cooldownOn = true;
} }
} }
@ -271,8 +270,8 @@ void ObjSwitch_SetOff(ObjSwitch* this, PlayState* play) {
if ((this->dyna.actor.params >> 4 & 7) == 1) { if ((this->dyna.actor.params >> 4 & 7) == 1) {
if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
this->cooldownOn = true;
} }
this->cooldownOn = true;
} }
} }
} }

View file

@ -6062,7 +6062,9 @@ s32 Player_ActionHandler_13(Player* this, PlayState* play) {
Inventory_ChangeAmmo(ITEM_BEAN, -1); Inventory_ChangeAmmo(ITEM_BEAN, -1);
Player_SetupActionPreserveItemAction(play, this, Player_Action_8084279C, 0); Player_SetupActionPreserveItemAction(play, this, Player_Action_8084279C, 0);
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
this->av2.actionVar2 = 0x50; if (GameInteractor_Should(VB_PLAY_BEAN_PLANTING_CS, true)) {
this->av2.actionVar2 = 0x50;
}
this->av1.actionVar1 = -1; this->av1.actionVar1 = -1;
} }
talkActor->flags |= ACTOR_FLAG_TALK; talkActor->flags |= ACTOR_FLAG_TALK;

View file

@ -122,8 +122,8 @@ void EffectSsEnIce_Draw(PlayState* play, u32 index, EffectSs* this) {
Gfx_SetupDL_25Xlu(play->state.gfxCtx); Gfx_SetupDL_25Xlu(play->state.gfxCtx);
func_8002EB44(&this->pos, &play->view.eye, &hiliteLightDir, play->state.gfxCtx); func_8002EB44(&this->pos, &play->view.eye, &hiliteLightDir, play->state.gfxCtx);
gSPSegment(POLY_XLU_DISP++, 0x08, gSPSegment(POLY_XLU_DISP++, 0x08,
Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, 0, gameplayFrames & 0xFF, 0x20, 0x10, 1, 0, Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, gameplayFrames & 0xFF, 0x20, 0x10, 1, 0,
(gameplayFrames * 2) & 0xFF, 0x40, 0x20, 0, 1, 0, 2)); (gameplayFrames * 2) & 0xFF, 0x40, 0x20));
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, this->rPrimColorR, this->rPrimColorG, this->rPrimColorB, gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, this->rPrimColorR, this->rPrimColorG, this->rPrimColorB,
this->rPrimColorA); this->rPrimColorA);
gDPSetEnvColor(POLY_XLU_DISP++, this->rEnvColorR, this->rEnvColorG, this->rEnvColorB, (u32)alpha); gDPSetEnvColor(POLY_XLU_DISP++, this->rEnvColorR, this->rEnvColorG, this->rEnvColorB, (u32)alpha);