mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-04-23 08:14:31 +00:00
Merge pull request #6497 from serprex/develop922
merge develop-ackbar 9.2.2 to develop
This commit is contained in:
commit
4cae72463e
|
|
@ -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")
|
||||
|
||||
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/lus-cvars.cmake)
|
||||
set(SPDLOG_LEVEL_TRACE 0)
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ extern "C" {
|
|||
#include "overlays/actors/ovl_En_Arrow/z_en_arrow.h"
|
||||
|
||||
s32 func_808351D4(Player* thisx, PlayState* play); // Arrow nocked
|
||||
s32 func_808353D8(Player* thisx, PlayState* play); // Aiming in first person
|
||||
void Player_InitItemAction(PlayState* play, Player* thisx, PlayerItemAction itemAction);
|
||||
void EnArrow_Init(Actor* thisx, PlayState* play);
|
||||
|
||||
extern PlayState* gPlayState;
|
||||
}
|
||||
|
|
@ -20,16 +19,6 @@ extern PlayState* gPlayState;
|
|||
|
||||
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[] = {
|
||||
PLAYER_IA_BOW,
|
||||
PLAYER_IA_BOW_FIRE,
|
||||
|
|
@ -54,11 +43,11 @@ static bool HasArrowType(PlayerItemAction itemAction) {
|
|||
case PLAYER_IA_BOW:
|
||||
return true;
|
||||
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:
|
||||
return (INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE);
|
||||
return INV_CONTENT(ITEM_ARROW_ICE) == ITEM_ARROW_ICE;
|
||||
case PLAYER_IA_BOW_LIGHT:
|
||||
return (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT);
|
||||
return INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT;
|
||||
default:
|
||||
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() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
|
||||
// don't allow cycling during minigames
|
||||
if (gSaveContext.minigameState == MINIGAME_STATUS_ACTIVE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !(player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && player->rideActor == NULL &&
|
||||
return LINK_IS_ADULT && !gSaveContext.minigameState && gPlayState->sceneNum != SCENE_SHOOTING_GALLERY &&
|
||||
!(player->stateFlags1 & PLAYER_STATE1_ON_HORSE) && player->rideActor == NULL &&
|
||||
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_LIGHT) == ITEM_ARROW_LIGHT);
|
||||
|
|
@ -113,66 +111,6 @@ static s8 GetNextArrowType(s8 currentArrowType) {
|
|||
static void UpdateButtonAlpha(s16 flashAlpha, bool isButtonBow, u16* buttonAlpha) {
|
||||
if (isButtonBow) {
|
||||
*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,73 +131,54 @@ static void UpdateEquippedBow(PlayState* play, s8 arrowType) {
|
|||
}
|
||||
|
||||
gSaveContext.buttonStatus[i] = BTN_ENABLED;
|
||||
sButtonFlashTimer = BUTTON_FLASH_DURATION;
|
||||
sButtonFlashCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateFlashEffect(play);
|
||||
}
|
||||
|
||||
static void CycleToNextArrow(PlayState* play, Player* player) {
|
||||
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() {
|
||||
bool ArrowCycleMain() {
|
||||
if (gPlayState == nullptr || !CanCycleArrows()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sJustCycledFrames > 0) {
|
||||
sJustCycledFrames--;
|
||||
}
|
||||
|
||||
UpdateFlashEffect(gPlayState);
|
||||
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Input* input = &gPlayState->state.input[0];
|
||||
|
||||
if (IsAimingBow(player) && CHECK_BTN_ANY(input->press.button, BTN_R)) {
|
||||
if (player->heldActor != NULL && player->heldActor->id == ACTOR_EN_ARROW) {
|
||||
if (IsHoldingMagicBow(player) && gSaveContext.magicState != MAGIC_STATE_IDLE && player->heldActor == NULL) {
|
||||
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
|
||||
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// reset magic state to IDLE before cycling to prevent error sound
|
||||
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() {
|
||||
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
|
||||
COND_VB_SHOULD(VB_EXECUTE_PLAYER_ACTION_FUNC, CVAR_ARROW_CYCLE_VALUE, {
|
||||
Player* player = (Player*)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)) {
|
||||
if (ArrowCycleMain()) {
|
||||
input->cur.button &= ~BTN_R;
|
||||
input->press.button &= ~BTN_R;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// don't consume magic on draw, but check if we have enough to fire
|
||||
|
|
@ -270,9 +189,9 @@ void RegisterArrowCycle() {
|
|||
|
||||
if (gSaveContext.magic < sMagicArrowCosts[magicArrowType]) {
|
||||
*arrowType = ARROW_NORMAL;
|
||||
}
|
||||
|
||||
} else {
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
|
||||
COND_VB_SHOULD(VB_EN_ARROW_MAGIC_CONSUMPTION, CVAR_ARROW_CYCLE_VALUE, {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ typedef enum {
|
|||
static AltTrapType roll = ADD_TRAP_MAX;
|
||||
static int statusTimer = -1;
|
||||
static int eventTimer = -1;
|
||||
static EntranceIndex teleportRoll = ENTR_MAX;
|
||||
|
||||
const char* altTrapTypeCvars[] = {
|
||||
CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"),
|
||||
|
|
@ -41,6 +42,12 @@ const char* altTrapTypeCvars[] = {
|
|||
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> enabledAddTraps;
|
||||
for (int i = 0; i < ADD_TRAP_MAX; i++) {
|
||||
|
|
@ -102,6 +109,7 @@ static void RollRandomTrap(uint64_t seed) {
|
|||
break;
|
||||
case ADD_TELEPORT_TRAP:
|
||||
eventTimer = 3;
|
||||
teleportRoll = ShipUtils::RandomElement(teleportDestinations, &state);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -135,32 +143,7 @@ static void OnPlayerUpdate() {
|
|||
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
|
||||
break;
|
||||
case ADD_TELEPORT_TRAP: {
|
||||
int entrance;
|
||||
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);
|
||||
GameInteractor::RawAction::TeleportPlayer(teleportRoll);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -84,7 +84,8 @@ static void DisableFixedCamera_RestoreAllCameraData() {
|
|||
|
||||
// Helper to check if a camera type is a fixed camera
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -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" });
|
||||
18
soh/soh/Enhancements/TimeSavers/SkipWaterGateDelay.cpp
Normal file
18
soh/soh/Enhancements/TimeSavers/SkipWaterGateDelay.cpp
Normal 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") });
|
||||
|
|
@ -109,19 +109,22 @@ void UpdateCurrentBGM(u16 seqKey, SeqType seqType) {
|
|||
}
|
||||
}
|
||||
|
||||
static uint64_t seeded_audio_state = 0;
|
||||
|
||||
void RandomizeGroup(SeqType type, bool manual = true) {
|
||||
std::vector<u16> values;
|
||||
|
||||
uint64_t localRngState = 0;
|
||||
uint64_t* shuffleState = nullptr;
|
||||
|
||||
if (!manual) {
|
||||
if (CVarGetInteger(CVAR_AUDIO("RandomizeAudioGenModes"), 0) == RANDOMIZE_ON_FILE_LOAD_SEEDED ||
|
||||
CVarGetInteger(CVAR_AUDIO("RandomizeAudioGenModes"), 0) == RANDOMIZE_ON_RANDO_GEN_ONLY) {
|
||||
int randomizeMode = CVarGetInteger(CVAR_AUDIO("RandomizeAudioGenModes"), 0);
|
||||
if (randomizeMode == RANDOMIZE_ON_FILE_LOAD_SEEDED || randomizeMode == RANDOMIZE_ON_RANDO_GEN_ONLY) {
|
||||
|
||||
uint32_t finalSeed = type + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
|
||||
: 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
|
||||
|
|
@ -141,7 +144,7 @@ void RandomizeGroup(SeqType type, bool manual = true) {
|
|||
if (!values.size())
|
||||
return;
|
||||
}
|
||||
ShipUtils::Shuffle(values, &seeded_audio_state);
|
||||
ShipUtils::Shuffle(values, shuffleState);
|
||||
for (const auto& [seqId, seqData] : AudioCollection::Instance->GetAllSequences()) {
|
||||
const std::string cvarKey = AudioCollection::Instance->GetCvarKey(seqData.sfxKey);
|
||||
const std::string cvarLockKey = AudioCollection::Instance->GetCvarLockKey(seqData.sfxKey);
|
||||
|
|
|
|||
|
|
@ -1889,11 +1889,11 @@ void DrawSillyTab() {
|
|||
|
||||
UIWidgets::Separator(true, true, 2.0f, 2.0f);
|
||||
|
||||
UIWidgets::CVarCheckbox("Let It Snow", CVAR_GENERAL("LetItSnow"),
|
||||
UIWidgets::CVarCheckbox(
|
||||
"Let It Snow", CVAR_GENERAL("LetItSnow"),
|
||||
UIWidgets::CheckboxOptions()
|
||||
.Color(THEME_COLOR)
|
||||
.Tooltip("Makes snow fall, changes chest texture colors to red and green, etc, for "
|
||||
"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);
|
||||
|
||||
|
|
@ -2104,24 +2104,28 @@ void ApplySideEffects(CosmeticOption& cosmeticOption) {
|
|||
}
|
||||
}
|
||||
|
||||
static uint64_t seeded_cosmetics_state = 0;
|
||||
|
||||
void RandomizeColor(CosmeticOption& cosmeticOption, bool manual = true) {
|
||||
ImVec4 randomColor;
|
||||
|
||||
if (!manual && CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), 0) == RANDOMIZE_ON_FILE_LOAD_SEEDED ||
|
||||
!manual && CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), 0) == RANDOMIZE_ON_RANDO_GEN_ONLY) {
|
||||
uint64_t local_seed_state = 0;
|
||||
uint64_t* randomState = nullptr;
|
||||
|
||||
if (!manual) {
|
||||
int randomizeMode = CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), 0);
|
||||
if (randomizeMode == RANDOMIZE_ON_FILE_LOAD_SEEDED || randomizeMode == RANDOMIZE_ON_RANDO_GEN_ONLY) {
|
||||
|
||||
uint32_t finalSeed = cosmeticOption.defaultColor.r + cosmeticOption.defaultColor.g +
|
||||
cosmeticOption.defaultColor.b + cosmeticOption.defaultColor.a +
|
||||
(IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
|
||||
: static_cast<uint32_t>(gSaveContext.ship.stats.fileCreatedAt));
|
||||
|
||||
randomColor = GetRandomValue(finalSeed, &seeded_cosmetics_state);
|
||||
} else {
|
||||
randomColor = GetRandomValue();
|
||||
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;
|
||||
newColor.r = static_cast<uint8_t>(randomColor.x * 255.0f);
|
||||
newColor.g = static_cast<uint8_t>(randomColor.y * 255.0f);
|
||||
|
|
|
|||
|
|
@ -52,16 +52,6 @@ typedef enum {
|
|||
/* 0x08 */ GI_COLOR_BLACK,
|
||||
} 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
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -227,6 +227,14 @@ typedef enum {
|
|||
// - `*BgIceShelter`
|
||||
VB_BG_ICE_SHELTER_MELT,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// this->timer > 0 && this->timer <= 100
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*BgSpot06Objects`
|
||||
VB_BG_SPOT06_OBJECTS_GATE_SKIP,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// gSaveContext.bgsFlag
|
||||
|
|
@ -1558,6 +1566,14 @@ typedef enum {
|
|||
// - `*BossGanondrof`
|
||||
VB_PHANTOM_GANON_DEATH_SCENE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_PLAY_BEAN_PLANTING_CS,
|
||||
|
||||
// #### `result`
|
||||
// ##### In `DoorWarp1_ChildWarpOut` - `SCENE_DODONGOS_CAVERN_BOSS`
|
||||
// ```c
|
||||
|
|
|
|||
|
|
@ -2327,12 +2327,12 @@ void StaticData::HintTable_Init() {
|
|||
{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]]#!^"
|
||||
"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#?^"
|
||||
"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]]#!^"
|
||||
"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}));
|
||||
|
||||
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#!^"
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc, bool mysteriou
|
|||
itemName = CustomMessage(RAND_GET_OVERRIDE(rc).GetTrickName());
|
||||
color = "%g";
|
||||
} 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.InsertNames({ itemName, CustomMessage(std::to_string(price)) });
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
|||
"et j'aurai quelque chose à te donner! [[color]]([[1]])%w");
|
||||
msg.InsertNumber(count);
|
||||
msg.Replace("[[color]]", item.GetColor());
|
||||
msg.InsertNames({ item.GetName() });
|
||||
msg.InsertNames({ item.GetHint().GetHintMessage().GetForCurrentLanguage() });
|
||||
msg.AutoFormat();
|
||||
msg.LoadIntoFont();
|
||||
*loadFromMessageTable = false;
|
||||
|
|
@ -155,12 +155,10 @@ void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
|||
/*french*/
|
||||
"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");
|
||||
msg.Replace("[[color]]", Rando::StaticData::RetrieveItem(
|
||||
RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet())
|
||||
.GetColor());
|
||||
msg.InsertNames(
|
||||
{ Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet())
|
||||
.GetName() });
|
||||
Rando::Item& item =
|
||||
Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet());
|
||||
msg.Replace("[[color]]", item.GetColor());
|
||||
msg.InsertNames({ item.GetHint().GetHintMessage().GetForCurrentLanguage() });
|
||||
msg.AutoFormat();
|
||||
msg.LoadIntoFont();
|
||||
*loadFromMessageTable = false;
|
||||
|
|
|
|||
|
|
@ -513,17 +513,13 @@ const HintText Hint::GetItemHintText(uint8_t slot, bool mysterious) const {
|
|||
auto ctx = Rando::Context::GetInstance();
|
||||
RandomizerCheck hintedCheck = locations[slot];
|
||||
RandomizerGet targetRG = ctx->GetItemLocation(hintedCheck)->GetPlacedRandomizerGet();
|
||||
CustomMessage msg;
|
||||
if (mysterious) {
|
||||
return StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM];
|
||||
} else if (!ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS) &&
|
||||
targetRG == RG_ICE_TRAP) { // RANDOTODO store in item hint instead of item
|
||||
msg = CustomMessage({ ctx->overrides[hintedCheck].GetTrickName() });
|
||||
} else if (targetRG == RG_ICE_TRAP) { // RANDOTODO store in item hint instead of item
|
||||
return HintText(CustomMessage({ ctx->overrides[hintedCheck].GetTrickName() }));
|
||||
} 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 {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "soh/SaveManager.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
#include "item_category_adj.h"
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
|
|
@ -370,6 +371,7 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() {
|
|||
GetItemID vanillaItem = (GetItemID)Rando::StaticData::RetrieveItem(vanillaRandomizerGet).GetItemID();
|
||||
GetItemEntry getItemEntry =
|
||||
Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)vanillaRandomizerGet);
|
||||
GetItemCategory getItemCategory = Randomizer_AdjustItemCategory(getItemEntry);
|
||||
|
||||
if (loc->HasObtained()) {
|
||||
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.
|
||||
!(getItemEntry.getItemId >= RG_DEKU_TREE_MAP && getItemEntry.getItemId <= RG_ICE_CAVERN_MAP &&
|
||||
getItemEntry.modIndex == MOD_RANDOMIZER) &&
|
||||
(getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK ||
|
||||
getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN ||
|
||||
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))))))) {
|
||||
(getItemCategory == ITEM_CATEGORY_JUNK || getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN ||
|
||||
getItemCategory == ITEM_CATEGORY_HEALTH || getItemCategory == ITEM_CATEGORY_LESSER))))) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 &&
|
||||
(receivedItemEntry.itemId == ITEM_HEART_PIECE || receivedItemEntry.itemId == ITEM_HEART_PIECE_2 ||
|
||||
receivedItemEntry.itemId == ITEM_HEART_CONTAINER)) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#include "soh_assets.h"
|
||||
#include "static_data.h"
|
||||
#include "SeedContext.h"
|
||||
#include "logic.h"
|
||||
#include "textures/icon_item_24_static/icon_item_24_static.h"
|
||||
#include "textures/icon_item_static/icon_item_static.h"
|
||||
#include "z64object.h"
|
||||
|
|
|
|||
|
|
@ -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, {}, {}, {
|
||||
//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, {
|
||||
|
|
@ -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, {}, {}, {
|
||||
//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, {}, {}, {
|
||||
|
|
|
|||
|
|
@ -30,17 +30,17 @@ void RegionTable_Init_DeathMountainCrater() {
|
|||
ENTRANCE(RR_DMC_CRACKED_WALL, (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()) ||
|
||||
(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()) ||
|
||||
(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()) ||
|
||||
(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()) ||
|
||||
(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()) ||
|
||||
(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()) ||
|
||||
(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, {
|
||||
|
|
@ -56,17 +56,17 @@ void RegionTable_Init_DeathMountainCrater() {
|
|||
ENTRANCE(RR_DMC_CRACKED_WALL, (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()) ||
|
||||
(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()) ||
|
||||
(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()) ||
|
||||
(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()) ||
|
||||
(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()) ||
|
||||
(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()) ||
|
||||
(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, {}, {
|
||||
|
|
@ -92,13 +92,13 @@ void RegionTable_Init_DeathMountainCrater() {
|
|||
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_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()) ||
|
||||
((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->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()) ||
|
||||
(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, {}, {
|
||||
|
|
@ -124,11 +124,11 @@ void RegionTable_Init_DeathMountainCrater() {
|
|||
ENTRANCE(RR_DMC_POTS, true),
|
||||
ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 8 || logic->Hearts() >= 2),
|
||||
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()) ||
|
||||
((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()) ||
|
||||
(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, {}, {
|
||||
|
|
@ -154,11 +154,11 @@ void RegionTable_Init_DeathMountainCrater() {
|
|||
ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2),
|
||||
ENTRANCE(RR_DMC_POT_GROTTO_EXIT, true),
|
||||
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()) ||
|
||||
((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()) ||
|
||||
(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, {}, {
|
||||
|
|
@ -188,7 +188,7 @@ void RegionTable_Init_DeathMountainCrater() {
|
|||
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))),
|
||||
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->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())),
|
||||
|
|
@ -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)))),
|
||||
ENTRANCE(RR_DMC_CENTRAL, logic->HasItem(RG_CLIMB) && (logic->FireTimer() >= 48 || logic->Hearts() >= 9)),
|
||||
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->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()))),
|
||||
|
|
|
|||
|
|
@ -4555,51 +4555,6 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
|
|||
if (INV_CONTENT(ITEM_BEAN) == ITEM_NONE) {
|
||||
INV_CONTENT(ITEM_BEAN) = ITEM_BEAN;
|
||||
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;
|
||||
case RG_DOUBLE_DEFENSE:
|
||||
|
|
|
|||
|
|
@ -24,11 +24,14 @@ extern "C" {
|
|||
#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_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_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_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_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_En_Ik/z_en_ik.h>
|
||||
#include <objects/object_gnd/object_gnd.h>
|
||||
|
|
@ -328,6 +331,15 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
|
|||
RateLimitedSuccessChime();
|
||||
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: {
|
||||
EnGo2* biggoron = (EnGo2*)actor;
|
||||
biggoron->isAwake = true;
|
||||
|
|
@ -376,8 +388,14 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
|
|||
RateLimitedSuccessChime();
|
||||
break;
|
||||
}
|
||||
case ACTOR_OBJ_LIGHTSWITCH: {
|
||||
ObjLightswitch* lightswitch = (ObjLightswitch*)actor;
|
||||
lightswitch->toggleDelay = 0;
|
||||
*should = false;
|
||||
RateLimitedSuccessChime();
|
||||
break;
|
||||
}
|
||||
case ACTOR_BG_ICE_SHUTTER:
|
||||
case ACTOR_OBJ_LIGHTSWITCH:
|
||||
case ACTOR_OBJ_SYOKUDAI:
|
||||
case ACTOR_OBJ_TIMEBLOCK:
|
||||
case ACTOR_EN_PO_SISTERS:
|
||||
|
|
@ -554,6 +572,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
|
|||
}
|
||||
break;
|
||||
}
|
||||
case VB_PLAY_BEAN_PLANTING_CS:
|
||||
case VB_PLAY_EYEDROP_CREATION_ANIM:
|
||||
case VB_PLAY_EYEDROPS_CS:
|
||||
case VB_PLAY_DROP_FISH_FOR_JABU_CS:
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
#include <nlohmann/json.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
#include <regex>
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <z64.h>
|
||||
|
|
@ -625,37 +624,37 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) {
|
|||
case kEffectTpLinksHouse:
|
||||
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
|
||||
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
|
||||
GI_TP_DEST_LINKSHOUSE;
|
||||
ENTR_LINKS_HOUSE_CHILD_SPAWN;
|
||||
break;
|
||||
case kEffectTpMinuet:
|
||||
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
|
||||
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
|
||||
GI_TP_DEST_MINUET;
|
||||
ENTR_SACRED_FOREST_MEADOW_WARP_PAD;
|
||||
break;
|
||||
case kEffectTpBolero:
|
||||
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
|
||||
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
|
||||
GI_TP_DEST_BOLERO;
|
||||
ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD;
|
||||
break;
|
||||
case kEffectTpSerenade:
|
||||
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
|
||||
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
|
||||
GI_TP_DEST_SERENADE;
|
||||
ENTR_LAKE_HYLIA_WARP_PAD;
|
||||
break;
|
||||
case kEffectTpRequiem:
|
||||
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
|
||||
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
|
||||
GI_TP_DEST_REQUIEM;
|
||||
ENTR_DESERT_COLOSSUS_WARP_PAD;
|
||||
break;
|
||||
case kEffectTpNocturne:
|
||||
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
|
||||
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
|
||||
GI_TP_DEST_NOCTURNE;
|
||||
ENTR_GRAVEYARD_WARP_PAD;
|
||||
break;
|
||||
case kEffectTpPrelude:
|
||||
effect->giEffect = std::make_unique<GameInteractionEffect::TeleportPlayer>();
|
||||
dynamic_cast<ParameterizedGameInteractionEffect*>(effect->giEffect.get())->parameters[0] =
|
||||
GI_TP_DEST_PRELUDE;
|
||||
ENTR_TEMPLE_OF_TIME_WARP_PAD;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -405,7 +405,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
|
|||
std::vector<std::string> args;
|
||||
if (argc > 1) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
args.push_back(argv[argc]);
|
||||
args.push_back(argv[i]);
|
||||
}
|
||||
}
|
||||
Extractor extract;
|
||||
|
|
@ -464,7 +464,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
|
|||
#elif (defined(__WIIU__) || defined(__SWITCH__))
|
||||
extractStep = ES_VERIFY;
|
||||
#else
|
||||
extractStep = ES_EXTRACT;
|
||||
extractStep = args.empty() ? ES_EXTRACT : ES_EXTRACT_ARGS;
|
||||
#endif
|
||||
} else {
|
||||
std::string msg;
|
||||
|
|
@ -549,11 +549,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
|
|||
"OK", "", [&]() { exit(0); });
|
||||
} else {
|
||||
windowsStep = WS_DONE;
|
||||
if (args.size() > 0) {
|
||||
extractStep = ES_EXTRACT_ARGS;
|
||||
} else {
|
||||
extractStep = ES_EXTRACT;
|
||||
}
|
||||
extractStep = args.empty() ? ES_EXTRACT : ES_EXTRACT_ARGS;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -564,7 +560,7 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
|
|||
}
|
||||
case ES_EXTRACT_ARGS: {
|
||||
#if !defined(__SWITCH__) && !defined(__WIIU__)
|
||||
if (args.size() == 0) {
|
||||
if (args.empty()) {
|
||||
SohGui::RegisterPopup(
|
||||
"Run Ship of Harkinian", "All files have been processed. Run SoH?", "Yes", "No",
|
||||
[&]() {
|
||||
|
|
|
|||
|
|
@ -1806,7 +1806,7 @@ void SohMenu::AddMenuEnhancements() {
|
|||
.CVar(CVAR_CHEAT("SpeedModifier.DoesntChangeJump"));
|
||||
AddWidget(path, "Multiplier:", WIDGET_CVAR_SLIDER_FLOAT)
|
||||
.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%%"));
|
||||
AddWidget(path, "Button Combination:", WIDGET_CVAR_BTN_SELECTOR)
|
||||
.CVar(CVAR_CHEAT("SpeedModifier.Btn"))
|
||||
|
|
|
|||
|
|
@ -1255,16 +1255,7 @@ bool CVarBtnSelector(const char* label, const char* cvarName, const BtnSelectorO
|
|||
}
|
||||
} // namespace UIWidgets
|
||||
|
||||
ImVec4 GetRandomValue() {
|
||||
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 GetRandomValue(uint64_t* state) {
|
||||
ImVec4 NewColor;
|
||||
NewColor.x = (float)ShipUtils::RandomDouble(state);
|
||||
NewColor.y = (float)ShipUtils::RandomDouble(state);
|
||||
|
|
|
|||
|
|
@ -1089,8 +1089,7 @@ void InsertHelpHoverText(const std::string& text);
|
|||
void InsertHelpHoverText(const char* text);
|
||||
} // namespace UIWidgets
|
||||
|
||||
ImVec4 GetRandomValue();
|
||||
ImVec4 GetRandomValue(uint32_t seed, uint64_t* state = nullptr);
|
||||
ImVec4 GetRandomValue(uint64_t* state = nullptr);
|
||||
|
||||
Color_RGBA8 RGBA8FromVec(ImVec4 vec);
|
||||
ImVec4 VecFromRGBA8(Color_RGBA8 color);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "z_bg_spot06_objects.h"
|
||||
#include "objects/object_spot06_objects/object_spot06_objects.h"
|
||||
#include "soh/Enhancements/custom-message/CustomMessageTypes.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
|
||||
#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.
|
||||
*/
|
||||
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--;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
} 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_MAIN_1].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;
|
||||
} else {
|
||||
// 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].zMin = WATER_LEVEL_RIVER_LOWER_Z - 50;
|
||||
play->colCtx.colHeader->waterBoxes[LHWB_MAIN_1].ySurface = yPos;
|
||||
|
|
|
|||
|
|
@ -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_F11], 255.0f, 1.0f, 10.0f);
|
||||
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)) {
|
||||
sKotakePtr->workf[UNK_F16] = 10.0f;
|
||||
|
|
@ -5037,9 +5037,8 @@ void BossTw_DrawEffects(PlayState* play) {
|
|||
if (sp18F == 0) {
|
||||
gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(gTwinrovaIceSurroundingPlayerMaterialDL));
|
||||
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, 255);
|
||||
gSPSegment(
|
||||
POLY_XLU_DISP++, 8,
|
||||
Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, 0, 0, 0x20, 0x20, 0, 0, 0, 0));
|
||||
gSPSegment(POLY_XLU_DISP++, 8,
|
||||
Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, 0, 0, 0x20, 0x20));
|
||||
sp18F++;
|
||||
BossTw_InitRand(1, 0x71AC, 0x263A);
|
||||
}
|
||||
|
|
@ -5091,9 +5090,8 @@ void BossTw_DrawEffects(PlayState* play) {
|
|||
}
|
||||
|
||||
gSPSegment(POLY_XLU_DISP++, 8,
|
||||
Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, (currentEffect->frame * 3) & 0x7F,
|
||||
(-currentEffect->frame * 15) & 0xFF, 0x20, 0x40, 1, 0, 0, 0x20, 0x20, 3, -15,
|
||||
0, 0));
|
||||
Gfx_TwoTexScroll(play->state.gfxCtx, 0, (currentEffect->frame * 3) & 0x7F,
|
||||
(-currentEffect->frame * 15) & 0xFF, 0x20, 0x40, 1, 0, 0, 0x20, 0x20));
|
||||
Matrix_Translate(currentEffect->pos.x, currentEffect->pos.y, currentEffect->pos.z, MTXMODE_NEW);
|
||||
Matrix_ReplaceRotation(&play->billboardMtxF);
|
||||
Matrix_Scale(currentEffect->workf[EFF_SCALE], currentEffect->workf[EFF_SCALE], 1.0f, MTXMODE_APPLY);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#include "objects/object_fz/object_fz.h"
|
||||
#include "soh/frame_interpolation.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ObjectExtension/ActorMaximumHealth.h"
|
||||
|
||||
#define FLAGS \
|
||||
(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);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08,
|
||||
Gfx_TwoTexScrollEx(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));
|
||||
Gfx_TwoTexScroll(play->state.gfxCtx, 0, 3 * (iceSmoke->timer + (3 * i)),
|
||||
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_ReplaceRotation(&play->billboardMtxF);
|
||||
Matrix_Scale(iceSmoke->xyScale, iceSmoke->xyScale, 1.0f, MTXMODE_APPLY);
|
||||
|
|
|
|||
|
|
@ -551,7 +551,9 @@ void ObjBean_WaitForBean(ObjBean* this, PlayState* play) {
|
|||
void func_80B8FE00(ObjBean* this) {
|
||||
this->actionFunc = func_80B8FE3C;
|
||||
ObjBean_SetDrawMode(this, BEAN_STATE_DRAW_LEAVES);
|
||||
if (GameInteractor_Should(VB_PLAY_BEAN_PLANTING_CS, true)) {
|
||||
this->timer = 60;
|
||||
}
|
||||
}
|
||||
|
||||
// Link is looking at the soft soil
|
||||
|
|
|
|||
|
|
@ -256,10 +256,9 @@ void ObjSwitch_SetOn(ObjSwitch* this, PlayState* play) {
|
|||
} else {
|
||||
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
|
||||
}
|
||||
}
|
||||
|
||||
this->cooldownOn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjSwitch_SetOff(ObjSwitch* this, PlayState* play) {
|
||||
|
|
@ -271,10 +270,10 @@ void ObjSwitch_SetOff(ObjSwitch* this, PlayState* play) {
|
|||
if ((this->dyna.actor.params >> 4 & 7) == 1) {
|
||||
if (GameInteractor_Should(VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
|
||||
}
|
||||
this->cooldownOn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjSwitch_UpdateTwoTexScrollXY(ObjSwitch* this) {
|
||||
|
|
|
|||
|
|
@ -6062,7 +6062,9 @@ s32 Player_ActionHandler_13(Player* this, PlayState* play) {
|
|||
Inventory_ChangeAmmo(ITEM_BEAN, -1);
|
||||
Player_SetupActionPreserveItemAction(play, this, Player_Action_8084279C, 0);
|
||||
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
|
||||
if (GameInteractor_Should(VB_PLAY_BEAN_PLANTING_CS, true)) {
|
||||
this->av2.actionVar2 = 0x50;
|
||||
}
|
||||
this->av1.actionVar1 = -1;
|
||||
}
|
||||
talkActor->flags |= ACTOR_FLAG_TALK;
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ void EffectSsEnIce_Draw(PlayState* play, u32 index, EffectSs* this) {
|
|||
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
||||
func_8002EB44(&this->pos, &play->view.eye, &hiliteLightDir, play->state.gfxCtx);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08,
|
||||
Gfx_TwoTexScrollEx(play->state.gfxCtx, 0, 0, gameplayFrames & 0xFF, 0x20, 0x10, 1, 0,
|
||||
(gameplayFrames * 2) & 0xFF, 0x40, 0x20, 0, 1, 0, 2));
|
||||
Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, gameplayFrames & 0xFF, 0x20, 0x10, 1, 0,
|
||||
(gameplayFrames * 2) & 0xFF, 0x40, 0x20));
|
||||
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, this->rPrimColorR, this->rPrimColorG, this->rPrimColorB,
|
||||
this->rPrimColorA);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, this->rEnvColorR, this->rEnvColorG, this->rEnvColorB, (u32)alpha);
|
||||
|
|
|
|||
Loading…
Reference in a new issue