Merge pull request #6497 from serprex/develop922

merge develop-ackbar 9.2.2 to develop
This commit is contained in:
Philip Dubé 2026-04-14 02:31:35 +00:00 committed by GitHub
commit 4cae72463e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
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")
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)

View file

@ -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, {

View file

@ -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:

View file

@ -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() {

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) {
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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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#!^"

View file

@ -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)) });

View file

@ -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;

View file

@ -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 {

View file

@ -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)) {

View file

@ -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"

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, {}, {}, {
//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, {}, {}, {

View file

@ -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()))),

View file

@ -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:

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_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:

View file

@ -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:

View file

@ -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",
[&]() {

View file

@ -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"))

View file

@ -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);

View file

@ -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);

View file

@ -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;

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_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);

View file

@ -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);

View file

@ -551,8 +551,10 @@ 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
void func_80B8FE3C(ObjBean* this, PlayState* play) {

View file

@ -256,11 +256,10 @@ 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) {
this->cooldownOn = false;
@ -271,11 +270,11 @@ 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) {
this->x1TexScroll = (this->x1TexScroll - 1) & 0x7F;

View file

@ -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;

View file

@ -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);