This commit is contained in:
Patrick12115 2024-11-11 15:44:35 -05:00
commit f15ebe1e1f
241 changed files with 3659 additions and 2459 deletions

12
soh/include/attributes.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef ATTRIBUTES_H
#define ATTRIBUTES_H
#if !defined(__GNUC__) && !defined(__attribute__)
#define __attribute__(x)
#endif
#define UNUSED __attribute__((unused))
#define FALLTHROUGH __attribute__((fallthrough))
#define NORETURN __attribute__((noreturn))
#endif

View File

@ -980,9 +980,9 @@ f32 Math_SmoothStepToDegF(f32* pValue, f32 target, f32 fraction, f32 step, f32 m
s16 Math_SmoothStepToS(s16* pValue, s16 target, s16 scale, s16 step, s16 minStep);
void Math_ApproachS(s16* pValue, s16 target, s16 scale, s16 step);
void Color_RGBA8_Copy(Color_RGBA8* dst, Color_RGBA8* src);
void func_80078884(u16 sfxId);
void func_800788CC(u16 sfxId);
void func_80078914(Vec3f* arg0, u16 sfxId);
void Sfx_PlaySfxCentered(u16 sfxId);
void Sfx_PlaySfxCentered2(u16 sfxId);
void Sfx_PlaySfxAtPos(Vec3f* arg0, u16 sfxId);
s16 getHealthMeterXOffset();
s16 getHealthMeterYOffset();
void HealthMeter_Init(PlayState* play);
@ -1419,18 +1419,6 @@ void ViMode_Init(ViMode* viMode);
void ViMode_Destroy(ViMode* viMode);
void ViMode_ConfigureFeatures(ViMode* viMode, s32 viFeatures);
void ViMode_Update(ViMode* viMode, Input* input);
void func_800ACE70(struct_801664F0* this);
void func_800ACE90(struct_801664F0* this);
void func_800ACE98(struct_801664F0* this, Gfx** gfxp);
void VisMono_Init(VisMono* this);
void VisMono_Destroy(VisMono* this);
void VisMono_UpdateTexture(VisMono* this, u16* tex);
Gfx* VisMono_DrawTexture(VisMono* this, Gfx* gfx);
void VisMono_Draw(VisMono* this, Gfx** gfxp);
void VisMono_DrawOld(VisMono* this);
void func_800AD920(struct_80166500* this);
void func_800AD950(struct_80166500* this);
void func_800AD958(struct_80166500* this, Gfx** gfxp);
void Skybox_Init(GameState* state, SkyboxContext* skyboxCtx, s16 skyboxId);
Mtx* SkyboxDraw_UpdateMatrix(SkyboxContext* skyboxCtx, f32 x, f32 y, f32 z);
void SkyboxDraw_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyboxId, s16 blend, f32 x, f32 y, f32 z);
@ -1536,9 +1524,9 @@ void KaleidoScopeCall_Init(PlayState* play);
void KaleidoScopeCall_Destroy(PlayState* play);
void KaleidoScopeCall_Update(PlayState* play);
void KaleidoScopeCall_Draw(PlayState* play);
void func_800BC490(PlayState* play, s16 point);
s32 func_800BC56C(PlayState* play, s16 arg1);
void func_800BC590(PlayState* play);
void Play_SetViewpoint(PlayState* play, s16 viewpoint);
s32 Play_CheckViewpoint(PlayState* play, s16 viewpoint);
void Play_SetShopBrowsingViewpoint(PlayState* play);
void Gameplay_SetupTransition(PlayState* play, s32 arg1);
Gfx* Play_SetFog(PlayState* play, Gfx* gfx);
void Play_Destroy(GameState* thisx);
@ -1552,7 +1540,7 @@ u8 CheckLACSRewardCount();
s32 Play_InCsMode(PlayState* play);
f32 func_800BFCB8(PlayState* play, MtxF* mf, Vec3f* vec);
void* Play_LoadFile(PlayState* play, RomFile* file);
void Play_SpawnScene(PlayState* play, s32 sceneNum, s32 spawn);
void Play_SpawnScene(PlayState* play, s32 sceneId, s32 spawn);
void func_800C016C(PlayState* play, Vec3f* src, Vec3f* dest);
s16 Play_CreateSubCamera(PlayState* play);
s16 Play_GetActiveCamId(PlayState* play);

9
soh/include/gfx.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef GFX_H
#define GFX_H
// Texture memory size, 4 KiB
#define TMEM_SIZE 0x1000
// Upstream TODO: Rest of this file
#endif

View File

@ -299,6 +299,10 @@ extern GraphicsContext* __gfxCtx;
#define BGCHECK_POS_ERROR_CHECK(vec3f) BgCheck_PosErrorCheck(vec3f, __FILE__, __LINE__)
#define SEG_ADDR(seg, addr) (addr | (seg << 24) | 1)
// Upstream TODO: Bring back decomp file/line macro use in src (but ignore the args for our needs)
#define SYSTEM_ARENA_MALLOC(size, file, line) SystemArena_MallocDebug(size, __FILE__, __LINE__)
#define SYSTEM_ARENA_FREE(ptr, file, line) SystemArena_FreeDebug(ptr, __FILE__, __LINE__)
// #endregion
#define DPAD_ITEM(button) ((gSaveContext.buttonStatus[(button) + 5] != BTN_DISABLED) \

View File

@ -120,7 +120,7 @@ extern "C"
extern KaleidoMgrOverlay gKaleidoMgrOverlayTable[KALEIDO_OVL_MAX];
extern KaleidoMgrOverlay* gKaleidoMgrCurOvl;
extern u8 gBossMarkState;
extern void* D_8012D1F0;
extern void* gDebugCutsceneScript;
extern s32 gScreenWidth;
extern s32 gScreenHeight;
extern Mtx gMtxClear;
@ -158,9 +158,9 @@ extern "C"
extern char D_80133398[];
extern SoundBankEntry* gSoundBanks[7];
extern u8 gSfxChannelLayout;
extern Vec3f D_801333D4;
extern f32 D_801333E0;
extern s8 D_801333E8;
extern Vec3f gSfxDefaultPos;
extern f32 gSfxDefaultFreqAndVolScale;
extern s8 gSfxDefaultReverb;
extern u8 D_801333F0;
extern u8 gAudioSfxSwapOff;
extern u8 D_80133408;
@ -203,7 +203,7 @@ extern "C"
extern f32 gBossMarkScale;
extern PauseMapMarksData* gLoadedPauseMarkDataTable;
extern s32 gTrnsnUnkState;
extern Color_RGBA8_u32 D_801614B0;
extern Color_RGBA8_u32 gVisMonoColor;
extern PreNmiBuff* gAppNmiBufferPtr;
extern SchedContext gSchedContext;
extern PadMgr gPadMgr;

View File

@ -3,6 +3,7 @@
#include <libultraship/libultra.h>
#include "unk.h" // this used to get pulled in via ultra64.h
#include "attributes.h"
#include "z64save.h"
#include "z64light.h"
#include "z64bgcheck.h"
@ -24,12 +25,14 @@
#include "z64skin.h"
#include "z64transition.h"
#include "z64interface.h"
#include "z64vis.h"
#include "alignment.h"
#include "sequence.h"
#include "sfx.h"
#include <libultraship/color.h>
#include "ichain.h"
#include "regs.h"
#include "gfx.h"
#if defined(__LP64__)
#define _SOH64
@ -2224,31 +2227,6 @@ typedef struct {
/* 0x0084 */ u32 unk_84;
} ViMode;
// Vis...
typedef struct {
/* 0x00 */ u32 type;
/* 0x04 */ u32 setScissor;
/* 0x08 */ Color_RGBA8_u32 color;
/* 0x0C */ Color_RGBA8_u32 envColor;
} struct_801664F0; // size = 0x10
typedef struct {
/* 0x00 */ u32 unk_00;
/* 0x04 */ u32 setScissor;
/* 0x08 */ Color_RGBA8_u32 primColor;
/* 0x0C */ Color_RGBA8_u32 envColor;
/* 0x10 */ u16* tlut;
/* 0x14 */ Gfx* monoDl;
} VisMono; // size = 0x18
// Vis...
typedef struct {
/* 0x00 */ u32 useRgba;
/* 0x04 */ u32 setScissor;
/* 0x08 */ Color_RGBA8_u32 primColor;
/* 0x08 */ Color_RGBA8_u32 envColor;
} struct_80166500; // size = 0x10
typedef struct {
/* 0x000 */ u8 rumbleEnable[4];
/* 0x004 */ u8 unk_04[0x40];

View File

@ -361,7 +361,7 @@ typedef enum {
/* 4 */ SCENE_LAYER_CUTSCENE_FIRST
} SceneLayer;
#define IS_CUTSCENE_LAYER (gSaveContext.sceneLayer >= SCENE_LAYER_CUTSCENE_FIRST)
#define IS_CUTSCENE_LAYER (gSaveContext.sceneSetupIndex >= SCENE_LAYER_CUTSCENE_FIRST)
typedef enum {
/* 0 */ LINK_AGE_ADULT,

101
soh/include/z64vis.h Normal file
View File

@ -0,0 +1,101 @@
#ifndef Z64_VIS_H
#define Z64_VIS_H
// #include "ultra64.h"
// #include "color.h"
#include <libultraship/libultra.h>
#ifdef __cplusplus
#define this thisx
extern "C"
{
#endif
typedef enum FramebufferFilterType {
/* 0 */ FB_FILTER_NONE,
/* 1 */ FB_FILTER_CVG_RGB,
/* 2 */ FB_FILTER_CVG_RGB_UNIFORM,
/* 3 */ FB_FILTER_CVG_ONLY,
/* 4 */ FB_FILTER_CVG_RGB_FOG, // Not recommended, easily overflows blender
/* 5 */ FB_FILTER_ZBUF_IA,
/* 6 */ FB_FILTER_ZBUF_RGBA,
/* 7 */ FB_FILTER_MONO
} FramebufferFilterType;
typedef enum VisScissorType {
/* 0 */ VIS_NO_SETSCISSOR,
/* 1 */ VIS_SETSCISSOR
} VisScissorType;
typedef struct Vis {
/* 0x00 */ u32 type;
/* 0x04 */ u32 scissorType;
/* 0x08 */ Color_RGBA8_u32 primColor;
/* 0x0C */ Color_RGBA8_u32 envColor;
} Vis; // size = 0x10
/* Cvg: Coverage */
#define FB_FILTER_TO_CVG_TYPE(filter) (filter)
typedef enum VisCvgType {
/* 0 */ VIS_CVG_TYPE_NONE = FB_FILTER_TO_CVG_TYPE(FB_FILTER_NONE),
/* 1 */ VIS_CVG_TYPE_CVG_RGB = FB_FILTER_TO_CVG_TYPE(FB_FILTER_CVG_RGB),
/* 2 */ VIS_CVG_TYPE_CVG_RGB_UNIFORM = FB_FILTER_TO_CVG_TYPE(FB_FILTER_CVG_RGB_UNIFORM),
/* 3 */ VIS_CVG_TYPE_CVG_ONLY = FB_FILTER_TO_CVG_TYPE(FB_FILTER_CVG_ONLY),
/* 4 */ VIS_CVG_TYPE_CVG_RGB_FOG = FB_FILTER_TO_CVG_TYPE(FB_FILTER_CVG_RGB_FOG)
} VisCvgType;
typedef struct VisCvg {
/* 0x00 */ Vis vis;
} VisCvg; // size = 0x10
void VisCvg_Init(VisCvg* this);
void VisCvg_Destroy(VisCvg* this);
void VisCvg_Draw(VisCvg* this, Gfx** gfxP);
/* Mono: Desaturation */
// Only one type
typedef struct VisMono {
/* 0x00 */ Vis vis;
/* 0x10 */ u16* tlut;
/* 0x14 */ Gfx* dList;
} VisMono; // size = 0x18
void VisMono_Init(VisMono* this);
void VisMono_Destroy(VisMono* this);
void VisMono_Draw(VisMono* this, Gfx** gfxP);
/* ZBuf: Z-Buffer */
#define FB_FILTER_TO_ZBUF_TYPE(filter) ((filter) - FB_FILTER_ZBUF_IA)
typedef enum VisZBufType {
/* 0 */ VIS_ZBUF_TYPE_IA = FB_FILTER_TO_ZBUF_TYPE(FB_FILTER_ZBUF_IA),
/* 1 */ VIS_ZBUF_TYPE_RGBA = FB_FILTER_TO_ZBUF_TYPE(FB_FILTER_ZBUF_RGBA)
} VisZBufType;
typedef struct VisZBuf {
/* 0x00 */ Vis vis;
} VisZBuf; // size = 0x10
void VisZBuf_Init(VisZBuf* this);
void VisZBuf_Destroy(VisZBuf* this);
void VisZBuf_Draw(VisZBuf* this, Gfx** gfxP);
#ifdef __cplusplus
#undef this
}
#endif
#endif

View File

@ -3,35 +3,43 @@
#include "soh/OTRGlobals.h"
extern "C" {
#include "macros.h"
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
#include "z64save.h"
#include "functions.h"
#include "variables.h"
#include "macros.h"
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
#include "z64save.h"
#include "functions.h"
#include "variables.h"
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex()
static bool sEnteredBlueWarp = false;
/**
* This will override the transitions into the blue warp cutscenes, set any appropriate flags, and
* set the entrance index to where you would normally end up after the blue warp cutscene. This
* should also account for the difference between your first and following visits to the blue warp.
*/
void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
uint8_t isBlueWarpCutscene = 0;
bool overrideBlueWarpDestinations =
IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF);
// Force blue warp skip on when ER needs to place Link somewhere else.
// This is preferred over having story cutscenes play in the overworld and then reloading Link somewhere else after.
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) || overrideBlueWarpDestinations) {
bool isBlueWarpCutscene = false;
// Deku Tree Blue warp
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) {
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP;
isBlueWarpCutscene = 1;
isBlueWarpCutscene = true;
// Dodongo's Cavern Blue warp
} else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT && gSaveContext.cutsceneIndex == 0xFFF1) {
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP;
isBlueWarpCutscene = 1;
isBlueWarpCutscene = true;
// Jabu Jabu's Blue warp
} else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP && gSaveContext.cutsceneIndex == 0xFFF0) {
gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP;
isBlueWarpCutscene = 1;
isBlueWarpCutscene = true;
// Forest Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) {
// Normally set in the blue warp cutscene
@ -43,14 +51,14 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_12;
}
isBlueWarpCutscene = 1;
isBlueWarpCutscene = true;
// Fire Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE && gSaveContext.cutsceneIndex == 0xFFF3) {
// Normally set in the blue warp cutscene
Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED);
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = 1;
isBlueWarpCutscene = true;
// Water Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) {
// Normally set in the blue warp cutscene
@ -58,15 +66,15 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER);
gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = 1;
isBlueWarpCutscene = true;
// Spirit Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) {
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = 1;
isBlueWarpCutscene = true;
// Shadow Temple Blue warp
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) {
gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP;
isBlueWarpCutscene = 1;
isBlueWarpCutscene = true;
}
if (isBlueWarpCutscene) {
@ -80,10 +88,20 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l
}
// This is outside the above condition because we want to handle both first and following visits to the blue warp
if (IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) {
if (sEnteredBlueWarp && overrideBlueWarpDestinations) {
Entrance_OverrideBlueWarp();
}
}
sEnteredBlueWarp = false;
}
/**
* Using this hook to simply observe that Link has entered a bluewarp
* This way we know to allow entrance rando overrides to be processed on the next tranisition hook
*/
void SkipBlueWarp_ShouldPlayBlueWarpCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
sEnteredBlueWarp = true;
}
/**
@ -143,6 +161,7 @@ void SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished(GIVanillaBehavior _,
void SkipBlueWarp_Register() {
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO, SkipBlueWarp_OnActorUpdate);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished);
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_GIVE_ITEM_FROM_BLUE_WARP, SkipBlueWarp_ShouldGiveItem);
}

View File

@ -14,7 +14,7 @@ void SkipDekuTreeIntro_Register() {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
BgTreemouth* treeMouth = va_arg(args, BgTreemouth*);
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
BgTreemouth_SetupAction(treeMouth, func_808BC6F8);
*should = false;
}

View File

@ -1174,7 +1174,7 @@ void ActorViewerWindow::DrawElement() {
Actor_Spawn(&gPlayState->actorCtx, gPlayState, newActor.id, newActor.pos.x, newActor.pos.y,
newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params, 0);
} else {
func_80078884(NA_SE_SY_ERROR);
Sfx_PlaySfxCentered(NA_SE_SY_ERROR);
}
}
@ -1187,7 +1187,7 @@ void ActorViewerWindow::DrawElement() {
newActor.pos.y, newActor.pos.z, newActor.rot.x, newActor.rot.y,
newActor.rot.z, newActor.params);
} else {
func_80078884(NA_SE_SY_ERROR);
Sfx_PlaySfxCentered(NA_SE_SY_ERROR);
}
}
}

View File

@ -8,6 +8,7 @@
#include <libultraship/bridge.h>
#include <libultraship/libultraship.h>
#include "soh/OTRGlobals.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
extern "C" {
#include <z64.h>
@ -276,11 +277,6 @@ void CreateSphereData() {
sphereGfx.push_back(gsSPEndDisplayList());
}
void ColViewerWindow::InitElement() {
CreateCylinderData();
CreateSphereData();
}
// Initializes the display list for a ColRenderSetting
void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
uint32_t rm;
@ -689,3 +685,10 @@ extern "C" void DrawColViewer() {
CLOSE_DISPS(gPlayState->state.gfxCtx);
}
void ColViewerWindow::InitElement() {
CreateCylinderData();
CreateSphereData();
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayDrawEnd>(DrawColViewer);
}

View File

@ -342,6 +342,7 @@ typedef enum {
VB_SHOULD_GIVE_VANILLA_FISHING_PRIZE,
VB_GIVE_RANDO_FISHING_PRIZE,
VB_PLAY_THROW_ANIMATION,
VB_INFLICT_VOID_DAMAGE,
/*** Give Items ***/

View File

@ -341,7 +341,7 @@ void GameInteractor::RawAction::UpdateActor(void* refActor) {
}
void GameInteractor::RawAction::TeleportPlayer(int32_t nextEntrance) {
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
gPlayState->nextEntranceIndex = nextEntrance;
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;

View File

@ -215,12 +215,12 @@ namespace Rando {
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) {
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
pauseCtx->cursorSpecialPos = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
}
@ -230,7 +230,7 @@ namespace Rando {
if (shouldScroll) {
entry->SetYOffset(yOffset);
yOffset += 18;
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
Matrix_Push();
entry->Draw(play, &mEntryDl);

View File

@ -64,15 +64,6 @@ static const ALIGN_ASSET(2) char tokinoma_room_0DL_007A70[] = dtokinoma_room_0DL
#define dtokinoma_room_0DL_007FD0 "__OTR__scenes/shared/tokinoma_scene/tokinoma_room_0DL_007FD0"
static const ALIGN_ASSET(2) char tokinoma_room_0DL_007FD0[] = dtokinoma_room_0DL_007FD0;
// TODO: When there's more uses of something like this, create a new GI::RawAction?
void ReloadSceneTogglingLinkAge() {
gPlayState->nextEntranceIndex = gSaveContext.entranceIndex;
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_CIRCLE(TCA_WAVE, TCC_WHITE, TCS_FAST); // Fade Out
gSaveContext.nextTransitionType = TRANS_TYPE_CIRCLE(TCA_WAVE, TCC_WHITE, TCS_FAST);
gPlayState->linkAgeOnLoad ^= 1; // toggle linkAgeOnLoad
}
void RegisterInfiniteMoney() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!GameInteractor::IsSaveLoaded(true)) return;
@ -219,42 +210,43 @@ void RegisterFreezeTime() {
}
/// Switches Link's age and respawns him at the last entrance he entered.
void RegisterSwitchAge() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
static bool warped = false;
void SwitchAge() {
if (gPlayState == NULL) return;
if (!GameInteractor::IsSaveLoaded(true)) {
CVarClear(CVAR_GENERAL("SwitchAge"));
warped = false;
return;
Player* player = GET_PLAYER(gPlayState);
// Hyrule Castle: Very likely to fall through floor, so we force a specific entrance
if (gPlayState->sceneNum == SCENE_HYRULE_CASTLE || gPlayState->sceneNum == SCENE_OUTSIDE_GANONS_CASTLE) {
gPlayState->nextEntranceIndex = ENTR_CASTLE_GROUNDS_SOUTH_EXIT;
} else {
gSaveContext.respawnFlag = 1;
gPlayState->nextEntranceIndex = gSaveContext.entranceIndex;
// Preserve the player's position and orientation
gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = gPlayState->nextEntranceIndex;
gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex = gPlayState->roomCtx.curRoom.num;
gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = player->actor.world.pos;
gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = player->actor.shape.rot.y;
if (gPlayState->roomCtx.curRoom.behaviorType2 < 4) {
gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0x0DFF;
} else {
// Scenes with static backgrounds use a special camera we need to preserve
Camera* camera = GET_ACTIVE_CAM(gPlayState);
s16 camId = camera->camDataIdx;
gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0x0D00 | camId;
}
}
static Vec3f playerPos;
static int16_t playerYaw;
static RoomContext* roomCtx;
static s32 roomNum;
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_INSTANT;
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST;
gPlayState->linkAgeOnLoad ^= 1;
if (CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) && !warped) {
playerPos = GET_PLAYER(gPlayState)->actor.world.pos;
playerYaw = GET_PLAYER(gPlayState)->actor.shape.rot.y;
roomCtx = &gPlayState->roomCtx;
roomNum = roomCtx->curRoom.num;
ReloadSceneTogglingLinkAge();
warped = true;
}
if (warped && gPlayState->transitionTrigger != TRANS_TRIGGER_START &&
gSaveContext.nextTransitionType == TRANS_NEXT_TYPE_DEFAULT) {
GET_PLAYER(gPlayState)->actor.shape.rot.y = playerYaw;
GET_PLAYER(gPlayState)->actor.world.pos = playerPos;
if (roomNum != roomCtx->curRoom.num) {
func_8009728C(gPlayState, roomCtx, roomNum); //load original room
//func_800973FC(gPlayState, &gPlayState->roomCtx); // commit to room load?
func_80097534(gPlayState, roomCtx); // load map for new room (unloading the previous room)
}
warped = false;
CVarClear(CVAR_GENERAL("SwitchAge"));
}
static HOOK_ID hookId = 0;
hookId = REGISTER_VB_SHOULD(VB_INFLICT_VOID_DAMAGE, {
*should = false;
GameInteractor::Instance->UnregisterGameHookForID<GameInteractor::OnVanillaBehavior>(hookId);
});
}
@ -262,8 +254,7 @@ void RegisterSwitchAge() {
void RegisterOcarinaTimeTravel() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnOcarinaSongAction>([]() {
if (!GameInteractor::IsSaveLoaded(true)) {
CVarClear(CVAR_ENHANCEMENT("TimeTravel"));
if (!GameInteractor::IsSaveLoaded(true) || !CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0)) {
return;
}
@ -273,22 +264,14 @@ void RegisterOcarinaTimeTravel() {
Actor* nearbyOcarinaSpot = Actor_FindNearby(gPlayState, player, ACTOR_EN_OKARINA_TAG, ACTORCAT_PROP, 120.0f);
Actor* nearbyDoorOfTime = Actor_FindNearby(gPlayState, player, ACTOR_DOOR_TOKI, ACTORCAT_BG, 500.0f);
Actor* nearbyFrogs = Actor_FindNearby(gPlayState, player, ACTOR_EN_FR, ACTORCAT_NPC, 300.0f);
uint8_t hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER);
uint8_t hasOcarinaOfTime = (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME);
// If TimeTravel + Player have the Ocarina of Time + Have Master Sword + is in proper range
bool justPlayedSoT = gPlayState->msgCtx.lastPlayedSong == OCARINA_SONG_TIME;
bool notNearAnySource = !nearbyTimeBlockEmpty && !nearbyTimeBlock && !nearbyOcarinaSpot && !nearbyDoorOfTime && !nearbyFrogs;
bool hasOcarinaOfTime = (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME);
bool doesntNeedOcarinaOfTime = CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2;
bool hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER);
// TODO: Once Swordless Adult is fixed: Remove the Master Sword check
if (((CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 1 && hasOcarinaOfTime) || CVarGetInteger(CVAR_ENHANCEMENT("TimeTravel"), 0) == 2) && hasMasterSword &&
gPlayState->msgCtx.lastPlayedSong == OCARINA_SONG_TIME && !nearbyTimeBlockEmpty && !nearbyTimeBlock &&
!nearbyOcarinaSpot && !nearbyFrogs) {
if (IS_RANDO) {
CVarSetInteger(CVAR_GENERAL("SwitchTimeline"), 1);
} else if (!IS_RANDO && !nearbyDoorOfTime) {
// This check is made for when Link is learning the Song Of Time in a vanilla save file that load a
// Temple of Time scene where the only object present is the Door of Time
CVarSetInteger(CVAR_GENERAL("SwitchTimeline"), 1);
}
ReloadSceneTogglingLinkAge();
if (justPlayedSoT && notNearAnySource && (hasOcarinaOfTime || doesntNeedOcarinaOfTime) && hasMasterSword) {
SwitchAge();
}
});
}
@ -1148,7 +1131,7 @@ void RegisterAltTrapTypes() {
eventTimer = 3;
break;
case ADD_SPEED_TRAP:
Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
GameInteractor::State::RunSpeedModifier = -2;
statusTimer = 200;
Overlay_DisplayText(10, "Speed Decreased!");
@ -1157,7 +1140,7 @@ void RegisterAltTrapTypes() {
eventTimer = 3;
break;
case ADD_VOID_TRAP:
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
eventTimer = 3;
break;
case ADD_AMMO_TRAP:
@ -1197,7 +1180,7 @@ void RegisterAltTrapTypes() {
AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5;
AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5;
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break;
case ADD_TELEPORT_TRAP: {
int entrance;
@ -1492,7 +1475,6 @@ void InitMods() {
RegisterEzQPA();
RegisterUnrestrictedItems();
RegisterFreezeTime();
RegisterSwitchAge();
RegisterOcarinaTimeTravel();
RegisterAutoSave();
RegisterDaytimeGoldSkultullas();

View File

@ -18,6 +18,7 @@ void UpdateHyperBossesState();
void InitMods();
void UpdatePatchHand();
void UpdateNoMSPatch();
void SwitchAge();
#ifdef __cplusplus
}

View File

@ -201,7 +201,7 @@ extern "C" void NameTag_RegisterForActorWithOptions(Actor* actor, const char* te
processedText.erase(std::remove_if(processedText.begin(), processedText.end(), [](const char& c) {
// 172 is max supported texture for the in-game font system,
// and filter anything less than a space but not the newline or nul characters
return c > (s8)172 || (c < ' ' && c != '\n' && c != '\0');
return (unsigned char)c > 172 || (c < ' ' && c != '\n' && c != '\0');
}), processedText.end());
int16_t numChar = processedText.length();

View File

@ -353,8 +353,6 @@ const std::vector<const char*> cheatCvars = {
CVAR_DEVELOPER_TOOLS("SaveFileID"),
CVAR_CHEAT("EnableBetaQuest"),
CVAR_DEVELOPER_TOOLS("BetterDebugWarpScreen"),
CVAR_GENERAL("SwitchAge"),
CVAR_GENERAL("SwitchTimeline"),
CVAR_CHEAT("NoRedeadFreeze"),
CVAR_CHEAT("NoKeeseGuayTarget"),
CVAR_CHEAT("BombTimerMultiplier"),

View File

@ -211,6 +211,14 @@ bool Here(const RandomizerRegion region, ConditionFn condition) {
return areaTable[region].Here(condition);
}
bool MQSpiritSharedStatueRoom(const RandomizerRegion region, ConditionFn condition, bool anyAge) {
return areaTable[region].MQSpiritShared(condition, false, anyAge);
}
bool MQSpiritSharedBrokenWallRoom(const RandomizerRegion region, ConditionFn condition, bool anyAge) {
return areaTable[region].MQSpiritShared(condition, true, anyAge);
}
bool CanPlantBean(const RandomizerRegion region) {
return areaTable[region].CanPlantBeanCheck();
}
@ -256,7 +264,7 @@ void RegionTable_Init() {
LOCATION(RC_SARIA_SONG_HINT, logic->CanUse(RG_SARIAS_SONG)),
}, {
//Exits
Entrance(RR_ROOT_EXITS, {[]{return true;}})
Entrance(RR_ROOT_EXITS, {[]{return true;}}),
});
areaTable[RR_ROOT_EXITS] = Region("Root Exits", "", {RA_LINKS_POCKET}, NO_DAY_NIGHT_CYCLE, {}, {}, {

View File

@ -18,54 +18,54 @@ extern std::shared_ptr<Rando::Logic> logic;
class EventAccess {
public:
explicit EventAccess(bool* event_, std::vector<ConditionFn> conditions_met_)
: event(event_) {
conditions_met.resize(2);
for (size_t i = 0; i < conditions_met_.size(); i++) {
conditions_met[i] = conditions_met_[i];
}
explicit EventAccess(bool* event_, std::vector<ConditionFn> conditions_met_)
: event(event_) {
conditions_met.resize(2);
for (size_t i = 0; i < conditions_met_.size(); i++) {
conditions_met[i] = conditions_met_[i];
}
}
bool ConditionsMet() const {
auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
return true;
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
return conditions_met[0]();
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) {
if (conditions_met[0]()) {
return true;
} else if (conditions_met[1] != NULL) {
return conditions_met[1]();
}
}
return false;
bool ConditionsMet() const {
auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
return true;
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
return conditions_met[0]();
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) {
if (conditions_met[0]()) {
return true;
} else if (conditions_met[1] != NULL) {
return conditions_met[1]();
}
}
return false;
}
bool CheckConditionAtAgeTime(bool& age, bool& time) {
bool CheckConditionAtAgeTime(bool& age, bool& time) {
logic->IsChild = false;
logic->IsAdult = false;
logic->AtDay = false;
logic->AtNight = false;
logic->IsChild = false;
logic->IsAdult = false;
logic->AtDay = false;
logic->AtNight = false;
time = true;
age = true;
time = true;
age = true;
return ConditionsMet();
}
return ConditionsMet();
}
void EventOccurred() {
*event = true;
}
void EventOccurred() {
*event = true;
}
bool GetEvent() const {
return *event;
}
bool GetEvent() const {
return *event;
}
private:
bool* event;
std::vector<ConditionFn> conditions_met;
bool* event;
std::vector<ConditionFn> conditions_met;
};
std::string CleanCheckConditionString(std::string condition);
@ -76,49 +76,49 @@ std::string CleanCheckConditionString(std::string condition);
class LocationAccess {
public:
explicit LocationAccess(RandomizerCheck location_, std::vector<ConditionFn> conditions_met_)
: location(location_), condition_str("") {
conditions_met.resize(2);
for (size_t i = 0; i < conditions_met_.size(); i++) {
conditions_met[i] = conditions_met_[i];
}
explicit LocationAccess(RandomizerCheck location_, std::vector<ConditionFn> conditions_met_)
: location(location_), condition_str("") {
conditions_met.resize(2);
for (size_t i = 0; i < conditions_met_.size(); i++) {
conditions_met[i] = conditions_met_[i];
}
}
explicit LocationAccess(RandomizerCheck location_, std::vector<ConditionFn> conditions_met_, std::string condition_str_)
: location(location_), condition_str(condition_str_) {
conditions_met.resize(2);
for (size_t i = 0; i < conditions_met_.size(); i++) {
conditions_met[i] = conditions_met_[i];
}
explicit LocationAccess(RandomizerCheck location_, std::vector<ConditionFn> conditions_met_, std::string condition_str_)
: location(location_), condition_str(condition_str_) {
conditions_met.resize(2);
for (size_t i = 0; i < conditions_met_.size(); i++) {
conditions_met[i] = conditions_met_[i];
}
}
bool GetConditionsMet() const {
auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
return true;
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
return conditions_met[0]();
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) {
if (conditions_met[0]()) {
return true;
} else if (conditions_met[1] != NULL) {
return conditions_met[1]();
}
}
return false;
bool GetConditionsMet() const {
auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
return true;
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
return conditions_met[0]();
} else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) {
if (conditions_met[0]()) {
return true;
} else if (conditions_met[1] != NULL) {
return conditions_met[1]();
}
}
return false;
}
bool CheckConditionAtAgeTime(bool& age, bool& time) const;
bool CheckConditionAtAgeTime(bool& age, bool& time) const;
bool ConditionsMet() const;
bool ConditionsMet() const;
RandomizerCheck GetLocation() const {
return location;
}
RandomizerCheck GetLocation() const {
return location;
}
std::string GetConditionStr() const {
return condition_str;
}
std::string GetConditionStr() const {
return condition_str;
}
protected:
RandomizerCheck location;
@ -138,127 +138,199 @@ namespace Rando {
class Region {
public:
Region();
Region(std::string regionName_, std::string scene_, std::set<RandomizerArea> areas,
Region();
Region(std::string regionName_, std::string scene_, std::set<RandomizerArea> areas,
bool timePass_,
std::vector<EventAccess> events_,
std::vector<LocationAccess> locations_,
std::list<Rando::Entrance> exits_);
~Region();
~Region();
std::string regionName;
std::string scene;
std::set<RandomizerArea> areas;
bool timePass;
std::vector<EventAccess> events;
std::vector<LocationAccess> locations;
std::list<Rando::Entrance> exits;
std::list<Rando::Entrance*> entrances;
//^ The above exits are now stored in a list instead of a vector because
//the entrance randomization algorithm plays around with pointers to these
//entrances a lot. By putting the entrances in a list, we don't have to
//worry about a vector potentially reallocating itself and invalidating all our
//entrance pointers.
std::string regionName;
std::string scene;
std::set<RandomizerArea> areas;
bool timePass;
std::vector<EventAccess> events;
std::vector<LocationAccess> locations;
std::list<Rando::Entrance> exits;
std::list<Rando::Entrance*> entrances;
//^ The above exits are now stored in a list instead of a vector because
//the entrance randomization algorithm plays around with pointers to these
//entrances a lot. By putting the entrances in a list, we don't have to
//worry about a vector potentially reallocating itself and invalidating all our
//entrance pointers.
bool childDay = false;
bool childNight = false;
bool adultDay = false;
bool adultNight = false;
bool addedToPool = false;;
bool childDay = false;
bool childNight = false;
bool adultDay = false;
bool adultNight = false;
bool addedToPool = false;;
void ApplyTimePass();
void ApplyTimePass();
bool UpdateEvents();
bool UpdateEvents();
void AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition);
void AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition);
void RemoveExit(Rando::Entrance* exitToRemove);
void RemoveExit(Rando::Entrance* exitToRemove);
void SetAsPrimary(RandomizerRegion exitToBePrimary);
void SetAsPrimary(RandomizerRegion exitToBePrimary);
Rando::Entrance* GetExit(RandomizerRegion exit);
Rando::Entrance* GetExit(RandomizerRegion exit);
bool Child() const {
return childDay || childNight;
bool Child() const {
return childDay || childNight;
}
bool Adult() const {
return adultDay || adultNight;
}
bool BothAgesCheck() const {
return Child() && Adult();
}
bool HasAccess() const {
return Child() || Adult();
}
bool AllAccess() const {
return childDay && childNight && adultDay && adultNight;
}
//Check to see if an exit can be access as both ages at both times of day
bool CheckAllAccess(RandomizerRegion exitKey);
std::set<RandomizerArea> GetAllAreas() const{
return areas;
}
RandomizerArea GetFirstArea() const{
if (areas.empty()){
assert(false);
return RA_NONE;
} else {
return *areas.begin();
}
}
bool Adult() const {
return adultDay || adultNight;
}
void ReplaceAreas(std::set<RandomizerArea> newAreas) {
areas = newAreas;
}
bool BothAgesCheck() const {
return Child() && Adult();
}
//Here checks conditional access based on whether or not both ages have
//access to this area. For example: if there are rocks that block a path
//which both child and adult can access, adult having hammer can give
//both child and adult access to the path.
bool Here(ConditionFn condition) {
bool HasAccess() const {
return Child() || Adult();
}
//store current age variables
bool pastAdult = logic->IsAdult;
bool pastChild = logic->IsChild;
bool AllAccess() const {
return childDay && childNight && adultDay && adultNight;
}
//set age access as this areas ages
logic->IsChild = Child();
logic->IsAdult = Adult();
//Check to see if an exit can be access as both ages at both times of day
bool CheckAllAccess(RandomizerRegion exitKey);
//heck condition as well as having at least child or adult access
bool hereVal = condition() && (logic->IsAdult || logic->IsChild);
std::set<RandomizerArea> GetAllAreas() const{
return areas;
}
//set back age variables
logic->IsChild = pastChild;
logic->IsAdult = pastAdult;
RandomizerArea GetFirstArea() const{
if (areas.empty()){
assert(false);
return RA_NONE;
} else {
return *areas.begin();
}
}
return hereVal;
}
void ReplaceAreas(std::set<RandomizerArea> newAreas) {
areas = newAreas;
}
bool CanPlantBeanCheck() const;
bool AllAccountedFor() const;
//Here checks conditional access based on whether or not both ages have
//access to this area. For example: if there are rocks that block a path
//which both child and adult can access, adult having hammer can give
//both child and adult access to the path.
bool Here(ConditionFn condition) {
void ResetVariables();
void printAgeTimeAccess() const {
auto message = "Child Day: " + std::to_string(childDay) + "\t"
"Child Night: " + std::to_string(childNight) + "\t"
"Adult Day: " + std::to_string(adultDay) + "\t"
"Adult Night: " + std::to_string(adultNight);
}
/*This logic covers checks that exist in the shared areas of MQ spirit from a glitchless standpoint.
This room has Quantum logic that I am currently handling with this function, however this is NOT suitable for glitch logic as it relies on specific ages
In this chunk there are 3 possibilities for passing a check, but first I have to talk about parallel universes.
In MQ Spirit key logic, we mostly care about 2 possibilities for how the player can spend keys, creating 2 Parralel universes
In the first universe, the player did not enter spirit as adult until after climbing as child, thus child spends keys linearly, only needing 2 to reach statue room.
In the second universe, the player went in as adult, possibly out of logic, and started wasting the keys to lock child out.
These Universes converge when the player has 7 keys (meaning adult can no longer lock child out) and adult is known to be able to reach Statue room. This creates "Certain Access", which is tracked seperatly for each age.
Child Certain Access is simple, if we have 7 keys and child access, it's Certain Access.
Adult Certain Access is also simple, adult is not key locked, so if they make it to a location, it's Certain Access.
Things get complicated when we handle the overlap of the 2 universes,
though an important detail is that if we have Certain Access as either age, we don't need to checked the overlap because overlap logic is strictly stricter than either Certain Access.
In order to track the first universe, the logic allows technical child access with the minimum number of keys, and then checks in this function for if we have 7 keys to determine if that is Certain or not.
This is for technical reasons, as areas with no access at all will simply not be checked.
Normally we would need to do similar shenanigans to track the second universe, however adult must have go through statue room to waste keys,
so can go back there and get new keys for Child to use if they do, and the navigation logic for shared MQ spirit from Statue Room is very simple for Adult.
Additionally, we don't need to know if adult can actually reach spirit temple or climb to statue room, because if the player can't do that, then universe 2 can't happen anyway,
and if the player does so out of logic, they can do it again, as the only consumable used sets a permanent flag.
The Adult Navigation logic is as such:
- Broken Wall room is 6 key locked, because if the player tries to spend 6 keys in a way that would block adults access, they would have to give child access instead.
- The child side hammer switch for the time travelling chest is 7 key locked for adult
- Reaching gauntlets hand is 7 key locked
- Going back into big block room is complex, but the only check there is child only so not a concern
- Everything else is possible with basic adult movement, or is impossible for child to reach glitchlessly
Anything 7 key locked does not need to be checked as shared, as all child access is Certain and because of this workaround we don't need to fake Adult access, meaning that is also Certain.
All of this combined means that when checking if adult can reach a location in universe 2, we only have to ask if it is a 6 key locked location or not.
Knowing all of this this, we can confirm things are logical in 3 different ways:
- If we have Adult Access, we know it is Certain Access, so they can get checks alone.
- If we have 7 keys, child has Certain Access as we know they cannot be locked out, so can get checks alone, otherwise we check the logical overlap
- If Child and Adult can get the check (ignoring actual adult access to the location), and the location is either not 6 key locked or we have 6 keys, we can get the check with the overlap*/
bool MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge = false) {
//if we have Certain Access as child, we can check anyAge and if true, resolve a condition with Here as if adult is here it's also Certain Access
if (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)){
if (anyAge){
return Here(condition);
}
return condition();
//else, if we are here as adult, we have Certain Access from that and don't need special handling for checking adult
} else if (Adult() && logic->IsAdult){
return condition();
//if we do not have Certain Access, we need to check the overlap by seeing if we are both here as child and meet the adult universe's access condition
//We only need to do it as child, as only child access matters for this check, as adult access is assumed based on keys
} else if (Child() && logic->IsChild && (!IsBrokenWall || logic->SmallKeys(RR_SPIRIT_TEMPLE, 6))) {
bool result = false;
//store current age variables
bool pastAdult = logic->IsAdult;
bool pastChild = logic->IsChild;
//set age access as this areas ages
logic->IsChild = Child();
logic->IsAdult = Adult();
//heck condition as well as having at least child or adult access
bool hereVal = condition() && (logic->IsAdult || logic->IsChild);
//First check if the check is possible as child
logic->IsChild = true;
logic->IsAdult = false;
result = condition();
//If so, check again as adult. both have to be true for result to be true
if (result) {
logic->IsChild = false;
logic->IsAdult = true;
result = condition();
}
//set back age variables
logic->IsChild = pastChild;
logic->IsAdult = pastAdult;
return hereVal;
}
bool CanPlantBeanCheck() const;
bool AllAccountedFor() const;
void ResetVariables();
void printAgeTimeAccess() const {
auto message = "Child Day: " + std::to_string(childDay) + "\t"
"Child Night: " + std::to_string(childNight) + "\t"
"Adult Day: " + std::to_string(adultDay) + "\t"
"Adult Night: " + std::to_string(adultNight);
return result;
}
return false;
}
};
extern std::array<Region, RR_MAX> areaTable;
extern std::vector<EventAccess> grottoEvents;
bool Here(const RandomizerRegion region, ConditionFn condition); //RANDOTODO make a less stupid way to check own at either age than self referncing with this
bool MQSpiritSharedStatueRoom(const RandomizerRegion region, ConditionFn condition, bool anyAge = false);
bool MQSpiritSharedBrokenWallRoom(const RandomizerRegion region, ConditionFn condition, bool anyAge = false);
bool CanPlantBean(const RandomizerRegion region);
bool BothAges(const RandomizerRegion region);
bool ChildCanAccess(const RandomizerRegion region);

View File

@ -32,7 +32,7 @@ void RegionTable_Init_GanonsCastle() {
Entrance(RR_GANONS_CASTLE_SHADOW_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL, {[]{return logic->CanUse(RG_GOLDEN_GAUNTLETS);}}),
Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
Entrance(RR_GANONS_TOWER_FLOOR_1, {[]{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
(logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) &&
(logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) &&
(logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) &&
@ -111,13 +111,6 @@ void RegionTable_Init_GanonsCastle() {
}, {});
}
areaTable[RR_GANONS_CASTLE_TOWER] = Region("Ganon's Castle Tower", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_GANONS_TOWER_BOSS_KEY_CHEST, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)),
LOCATION(RC_GANONDORF_HINT, logic->HasItem(RG_GANONS_CASTLE_BOSS_KEY) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))),
LOCATION(RC_GANON, logic->HasBossSoul(RG_GANON_SOUL) && logic->HasItem(RG_GANONS_CASTLE_BOSS_KEY) && logic->CanUse(RG_LIGHT_ARROWS) && logic->CanUse(RG_MASTER_SWORD)),
}, {});
/*---------------------------
| MASTER QUEST DUNGEON |
---------------------------*/
@ -142,7 +135,7 @@ void RegionTable_Init_GanonsCastle() {
Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_DINOLFOS_ROOM, {[]{return Here(RR_GANONS_CASTLE_MQ_MAIN, []{return logic->CanUse(RG_GOLDEN_GAUNTLETS);});}}),
//RANDOTODO could we just set these events automatically based on the setting?
Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
Entrance(RR_GANONS_TOWER_FLOOR_1, {[]{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
(logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) &&
(logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) &&
(logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) &&
@ -376,4 +369,53 @@ void RegionTable_Init_GanonsCastle() {
EventAccess(&logic->LightTrialClear, {[]{return logic->CanUse(RG_LIGHT_ARROWS);}}),
}, {}, {});
}
/*--------------------------
| TOWER AND ESCAPE |
---------------------------*/
areaTable[RR_GANONS_TOWER_FLOOR_1] = Region("Ganon's Tower Floor 1", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_GANONS_CASTLE_LOBBY, {[]{return Here(RR_GANONS_TOWER_FLOOR_1, []{return logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2);});}}),
Entrance(RR_GANONS_TOWER_FLOOR_2, {[]{return Here(RR_GANONS_TOWER_FLOOR_1, []{return logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2);});}}),
});
areaTable[RR_GANONS_TOWER_FLOOR_2] = Region("Ganon's Tower Floor 2", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_GANONS_TOWER_BOSS_KEY_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)),
}, {
//Exits
Entrance(RR_GANONS_TOWER_FLOOR_1, {[]{return Here(RR_GANONS_TOWER_FLOOR_2, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);});}}),
Entrance(RR_GANONS_TOWER_FLOOR_3, {[]{return Here(RR_GANONS_TOWER_FLOOR_2, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);});}}),
});
areaTable[RR_GANONS_TOWER_FLOOR_3] = Region("Ganon's Tower Floor 3", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_GANONS_TOWER_FLOOR_2, {[]{return Here(RR_GANONS_TOWER_FLOOR_3, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE, ED_CLOSE, true, 2);});}}),
Entrance(RR_GANONS_TOWER_GANONDORF_LAIR, {[]{return Here(RR_GANONS_TOWER_FLOOR_3, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE, ED_CLOSE, true, 2);}) && logic->HasItem(RG_GANONS_CASTLE_BOSS_KEY);}}),
});
areaTable[RR_GANONS_TOWER_GANONDORF_LAIR] = Region("Ganondorf's Lair", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_GANONDORF_HINT, logic->HasBossSoul(RG_GANON_SOUL)),
//18 pots
}, {
//Exits
Entrance(RR_GANONS_CASTLE_ESCAPE, {[]{return logic->CanKillEnemy(RE_GANONDORF);}}),
});
areaTable[RR_GANONS_CASTLE_ESCAPE] = Region("Ganon's Castle Escape", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//10 pots
}, {
//Exits
//temporary
Entrance(RR_GANONS_CASTLE_GANON_ARENA, {[]{return true;}}),
//real logic once we figure out how to deal with castle escape skip
//Entrance(RR_GANONS_CASTLE_GANON_ARENA, {[]{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);}}),
});
areaTable[RR_GANONS_CASTLE_GANON_ARENA] = Region("Ganon's Arena", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_GANON, logic->CanKillEnemy(RE_GANON)),
}, {});
}

View File

@ -209,7 +209,7 @@ void RegionTable_Init_GerudoTrainingGrounds() {
areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_STATUE_ROOM] = Region("Gerudo Training Grounds MQ Statue ROom", "Gerudo Training Grounds", {RA_GERUDO_TRAINING_GROUND}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW)),
LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW)),
}, {
//Exits
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STATUE_ROOM_LEDGE, {[]{return logic->CanUse(RG_LONGSHOT);}}),
@ -220,7 +220,7 @@ void RegionTable_Init_GerudoTrainingGrounds() {
//Locations
//implies logic->CanKillEnemy(RE_TORCH_SLUG)
LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE)),
LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanHitSwitch(ED_BOOMERANG)),
LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanHitSwitch(ED_BOMB_THROW)),
}, {
//Exits
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STATUE_ROOM, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_MQ_TORCH_SLUG_ROOM, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}}),

View File

@ -10,8 +10,8 @@ void RegionTable_Init_SpiritTemple() {
---------------------------*/
areaTable[RR_SPIRIT_TEMPLE_ENTRYWAY] = Region("Spirit Temple Entryway", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_LOBBY, {[]{return ctx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla();}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, {[]{return ctx->GetDungeon(SPIRIT_TEMPLE)->IsMQ();}}),
Entrance(RR_SPIRIT_TEMPLE_LOBBY, {[]{return ctx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla();}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, {[]{return ctx->GetDungeon(SPIRIT_TEMPLE)->IsMQ();}}),
Entrance(RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, {[]{return true;}}),
});
@ -137,102 +137,340 @@ void RegionTable_Init_SpiritTemple() {
if (ctx->GetDungeon(SPIRIT_TEMPLE)->IsMQ()) {
areaTable[RR_SPIRIT_TEMPLE_MQ_LOBBY] = Region("Spirit Temple MQ Lobby", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, true),
LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->BlastOrSmash();}) && ((logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)) || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)))),
LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->CanUse(RG_BOMBCHU_5) || (logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT))) || (logic->IsChild && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG)))),
LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, true),
LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()),
LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->CanHitSwitch(ED_BOOMERANG)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Spirit1FSilverRupees),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_CHILD, {[]{return logic->IsChild;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_ADULT, {[]{return logic->CanUse(RG_BOMBCHU_5) && logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS);}}),
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, {[]{return logic->IsChild;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH, {[]{return logic->CanUse(RG_LONGSHOT) && logic->CanUse(RG_BOMBCHU_5);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_CHILD] = Region("Spirit Temple MQ Child", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_SPIRIT_TEMPLE_MQ_1F_WEST] = Region("Spirit Temple MQ 1F West", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->FairyPot, {[]{return logic->FairyPot || (logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_SLINGSHOT));}}),
//not technically a rusted switch, but a boulder through a wall, but is part of the same trick on N64
EventAccess(&logic->MQSpiritCrawlBoulder, {[]{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}}),
}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->CanUse(RG_MEGATON_HAMMER);})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->CanUse(RG_DINS_FIRE)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BOMB_BAG)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, logic->CanUse(RG_BOMBCHU_5) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->CanUse(RG_FAIRY_SLINGSHOT) && (logic->CanUse(RG_DINS_FIRE) || (Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return logic->IsAdult && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_SONG_OF_TIME)));})))),
//Trick: logic->CanUse(RG_BOMBCHU_5) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->CanUse(RG_FAIRY_SLINGSHOT) && (logic->CanUse(RG_DINS_FIRE) || (SPIRIT_TEMPLE_MQ_ADULT.Adult() && logic->IsAdult && (logic->CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQFrozenEye && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_SONG_OF_TIME)))))
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, logic->MQSpiritTimeTravelChest),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SHARED, {[]{return logic->CanUse(RG_BOMBCHU_5) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_SOUTH, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->CanKillEnemy(RE_TORCH_SLUG);});}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->CanKillEnemy(RE_TORCH_SLUG);});}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, {[]{return logic->IsChild && logic->MQSpiritCrawlBoulder;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_ADULT] = Region("Spirit Temple MQ Adult", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_SOUTH] = Region("Spirit Temple MQ 1F Gibdo Room South", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_NORTH, {[]{return logic->CanUse(RG_BOMBCHU_5) && logic->CanHitEyeTargets();}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM, {[]{return logic->CanUse(RG_BOMBCHU_5) && logic->CanHitEyeTargets() && logic->CanKillEnemy(RE_GIBDO);}}),
});
// Room to store the 2 pots in to handle glitch logic going backwards around the loop later
areaTable[RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_NORTH] = Region("Spirit Temple MQ Gibdo Room North", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {});
areaTable[RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM] = Region("Spirit Temple Turntable Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//For non-fairy pot items, you can also get them with rang without killing the stalfos
EventAccess(&logic->FairyPot, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}}),
}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_NORTH, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_NORTH, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_NORTH] = Region("Spirit Temple MQ Map Room North", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->MQSpiritMapRoomEnemies, {[]{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE);}}),
}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanJumpslashExceptHammer() || logic->CanUse(RG_HOVER_BOOTS))),
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))),
LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 5)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_SONG_OF_TIME)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_SONG_OF_TIME) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))),
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->MQSpiritMapRoomEnemies),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT, {[]{return logic->CanUse(RG_MIRROR_SHIELD) && logic->IsAdult && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW)));}}),
//Trick: logic->CanUse(RG_MIRROR_SHIELD) && logic->IsAdult && (logic->CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQLowerAdult && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW)))
Entrance(RR_SPIRIT_TEMPLE_MQ_SHARED, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BOSS_AREA, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6) && logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanUse(RG_MEGATON_HAMMER);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanJumpslashExceptHammer() && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}}),
//Stalfos room blocks you in with fire until you kill the stalfos, which won't spawn from behind the fire
Entrance(RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH, {[]{return true;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_SHARED] = Region("Spirit Temple MQ Shared", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH] = Region("Spirit Temple MQ Map Room South", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//You can lure the keese over by aggroing them with dins if you use it as close to the torch keese as possible, but it's a trick as it's not intuitive and basically never comes up
EventAccess(&logic->MQSpiritMapRoomEnemies, {[]{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE, ED_BOOMERANG);}}),
}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 6)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, (logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)) || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)) || (logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_FAIRY_SLINGSHOT))),
LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || logic->IsAdult),
//Trick: logic->CanUse(RG_SONG_OF_TIME) || LogicSpiritMQSunBlockSoT || logic->IsAdult
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, (ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->CanUse(RG_BOOMERANG) && (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT))) || logic->IsAdult),
//Trick: (LogicSpiritMQSunBlockGS && logic->CanUse(RG_BOOMERANG) && (logic->CanUse(RG_SONG_OF_TIME) || LogicSpiritMQSunBlockSoT)) || logic->IsAdult
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || logic->IsAdult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanJumpslashExceptHammer() && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)));}}),
//Trick: (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && (logic->CanUse(RG_SONG_OF_TIME) || LogicSpiritMQSunBlockSoT || logic->IsAdult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SONG_OF_TIME) && (LogicLensSpiritMQ || logic->CanUse(RG_LENS_OF_TRUTH)))
Entrance(RR_DESERT_COLOSSUS, {[]{return (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || logic->IsAdult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanJumpslashExceptHammer() && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->IsAdult);}}),
//Trick: (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && (logic->CanUse(RG_SONG_OF_TIME) || LogicSpiritMQSunBlockSoT || logic->IsAdult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanUse(RG_SONG_OF_TIME) && (LogicLensSpiritMQ || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->IsAdult)
});
areaTable[RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT] = Region("Spirit Temple MQ Lower Adult", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, true),
LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_SUNS_SONG)
&& logic->CanUse(RG_SONG_OF_STORMS) && logic->CanUse(RG_ZELDAS_LULLABY)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->CanUse(RG_MEGATON_HAMMER)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, true),
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_SUNS_SONG)
&& logic->CanUse(RG_SONG_OF_STORMS) && logic->CanUse(RG_ZELDAS_LULLABY)),
}, {});
areaTable[RR_SPIRIT_TEMPLE_MQ_BOSS_AREA] = Region("Spirit Temple MQ Boss Region", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, true),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, {[]{return logic->CanUse(RG_MIRROR_SHIELD) && logic->CanUse(RG_HOOKSHOT);}}),
//The bridge is a temp flag, so not a way to cross south to north in logic
Entrance(RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_NORTH, {[]{return logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, {[]{return true;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD] =
Region("Spirit Temple MQ Inside Statue Head", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SHARED, { [] { return true; } }),
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY); } }),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH] = Region("Spirit Temple MQ West 1F Rusted Switch", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->MQSpiritTimeTravelChest, {[]{return logic->CanUse(RG_MEGATON_HAMMER);}}),
EventAccess(&logic->MQSpiritCrawlBoulder, {[]{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}}),
}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, {[]{return logic->IsChild && logic->MQSpiritCrawlBoulder;}}),
//This tracks possible child access, if adult has not entered STATUE_ROOM. Certain Child Access is checked for separately as 7 Keys
Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND] = Region("Spirit Temple MQ Mirror Shield Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//THIS REGION NEEDS MQSpiritSharedBrokenWallRoom WHEN ADDING THE POT
areaTable[RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE] = Region("Spirit Temple MQ Under Like Like", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
//This covers adult access only, as child arrives here from the other side of this door
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, {[]{return logic->CanHitSwitch();}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM] = Region("Spirit Temple MQ Broken Wall Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true),
}, {});
//Implies CanKillEnemy(RE_LIKE_LIKE)
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, MQSpiritSharedBrokenWallRoom(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->CanKillEnemy(RE_BEAMOS);})),
//Sunlights only temp spawn this chest, which is unintuitive/a bug.
//chest is only reachable as adult glitchlessly, so we can skip the shared in favour of IsAdult as adult access is always Certain
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, logic->IsAdult && logic->HasExplosives() && (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)) && logic->CanUse(RG_HOOKSHOT)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, {[]{return logic->CanHitSwitch();}}),
//This exit only governs child possible access, adult access starts on the other side so never checks this
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 2);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM] = Region("Spirit Temple MQ Statue Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, MQSpiritSharedStatueRoom(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanHitEyeTargets();})),
}, {
//Exits
//we check possible adult access directly in MQSpiritSharedBrokenWallRoom, so this exit only covers Certain Access
Entrance(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
//We can use Here instead of Shared here because adult will never need to rely on child access to reach this room, and adult access is Certain
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->HasFireSource() || (ctx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_SONG_OF_TIME));});}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, {[]{return logic->IsAdult || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || logic->CanUse(RG_SONG_OF_TIME);}}),
//explicit adult check here is a precaution against possible child logic leaking, child with a hookshot can do this
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, {[]{return logic->IsAdult && logic->CanUse(RG_HOOKSHOT);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM] = Region("Spirit Temple MQ Sun Block Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//We don't need Shared here because If we are checking as child, universe 2 adult access needs nothing so it always passes, and if we are checking as adult, it is Certain Access
LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, true),
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, MQSpiritSharedStatueRoom(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->CanUse(RG_BOOMERANG));})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, {[]{return true;}}),
//This door causes the Universes to merge as it requires 7 keys for both ages
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_IRON_KNUCKLE, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_WEST_IRON_KNUCKLE] = Region("Spirit Temple MQ East Iron Knuckle", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return logic->CanKillEnemy(RE_IRON_KNUCKLE);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND] = Region("Spirit Temple MQ Silver Gauntlets Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, true),
}, {});
}, {
//Exits
//If it is ever relevent for 1 age to spawn the mirror shield chest for the other can longshot across, it needs an eventAccess
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_IRON_KNUCKLE, {[]{return true;}}),
Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH] = Region("Spirit Temple MQ Block Room South", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, {[]{return true;}}),
//The block here is unusual in that it is a permanent flag, but reset anyway as child. This is because there's a check that would be blocked off by pushing them otherwise
//It may be worth considering making this always temp in future so adult doesn't have the same issue
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, {[]{return logic->IsChild ? logic->CanUse(RG_SILVER_GAUNTLETS) : Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->CanUse(RG_SILVER_GAUNTLETS);});}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH] = Region("Spirit Temple MQ Block Room North", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//Does not need to be shared as it's hard child locked, because adult pushing the block is a permanent flag that blocks the eye target and cannot be undone
LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 7) && logic->CanHitEyeTargets()),
}, {
//Exits
//if going to RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH from here is ever relevant, there needs to be an event to handle the block
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, {[]{return true;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST] = Region("Spirit Temple MQ Statue Room East", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_HOOKSHOT) & logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS))),
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, {[]{return true;}}),
//!QUANTUM LOGIC!
//We only need 4 keys, access to Shield hand and longshot to reach Gauntlets hand, as if we waste the 5th key we have given ourselves Gauntlets hand access through child climb
//This exit handles that possibility as cleanly as possible without quantum logic, but will not survive glitch logic
//logic->CanKillEnemy(RE_FLOORMASTER) is implied
Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) &&
logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) &&
logic->CanJumpslash() &&
(ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) &&
logic->CanKillEnemy(RE_IRON_KNUCKLE) &&
logic->CanUse(RG_LONGSHOT);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F, {[]{return logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && logic->CanUse(RG_DINS_FIRE));}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F] = Region("Spirit Temple MQ Three Suns Room 2F", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//implies logic->CanKillEnemy(RE_WALLMASTER). If we have lights, we can kill stalfos and wallmasters with bow
EventAccess(&logic->MQSpirit3SunsEnemies, {[]{return (logic->CanUse(RG_MIRROR_SHIELD) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)) ||
(ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}}),
}, {}, {
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F, {[]{return logic->MQSpirit3SunsEnemies;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F] = Region("Spirit Temple MQ Three Suns Room 1F", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F, {[]{return logic->MQSpirit3SunsEnemies;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, {[]{return true;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_1F_EAST] = Region("Spirit Temple MQ 1F East", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//Assumes RR_SPIRIT_TEMPLE_MQ_LOBBY access
EventAccess(&logic->Spirit1FSilverRupees, {[]{return logic->CanUse(RG_MEGATON_HAMMER);}}),
}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, {[]{return logic->CanUse(RG_MEGATON_HAMMER);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_LEEVER_ROOM, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_LEEVER_ROOM] = Region("Spirit Temple MQ Leever Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, logic->CanKillEnemy(RE_PURPLE_LEEVER) && logic->CanUse(RG_HOOKSHOT)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
}, {
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM] = Region("Spirit Temple MQ Symphony Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
//Implies CanPassEnemy(RE_MOBLIN_CHIEF)
Entrance(RR_SPIRIT_TEMPLE_MQ_AFTER_SYMPHONY_ROOM, {[]{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_EPONAS_SONG) &&
logic->CanUse(RG_SUNS_SONG) && logic->CanUse(RG_SONG_OF_STORMS) && logic->CanUse(RG_ZELDAS_LULLABY);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_AFTER_SYMPHONY_ROOM] = Region("Spirit Temple MQ After Symphony Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM, {[]{return true;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM] = Region("Spirit Temple MQ Four Beamos Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->CanKillEnemy(RE_BEAMOS)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, {[]{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, {[]{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM] = Region("Spirit Temple MQ SoT Sun Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, true),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, {[]{return logic->CanJumpslash();}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return (logic->IsAdult || logic->CanUse(RG_SONG_OF_TIME)) && logic->CanUse(RG_MIRROR_SHIELD);});}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND] = Region("Spirit Temple MQ East Stairs to Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE, {[]{return (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) &&
Here(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, []{return logic->CanKillEnemy(RE_FLOORMASTER);});}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE] = Region("Spirit Temple MQ East Iron Knuckle", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND] = Region("Spirit Temple MQ Mirror Shield Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return logic->CanUse(RG_LONGSHOT);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE, {[]{return true;}}),
Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM] = Region("Spirit Temple MQ 3F Gibdo Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, true),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, {[]{return true;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_WALL] = Region("Spirit Temple MQ Big Wall", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM, {[]{return true;}}),
//technically we only need to avoid them, but the sheer height and the moving walls makes getting to the top after only stunning them very difficult/impossible
//The silver rupees are irrelevant without silver shuffle
Entrance(RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, {[]{return logic->CanKillEnemy(RE_KEESE);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL] = Region("Spirit Temple MQ 4F Central", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_NINE_CHAIRS_ROOM, {[]{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_NINE_CHAIRS_ROOM] = Region("Spirit Temple MQ Nine Chairs Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//These skulls rely on the iron knuckle existing without a trick to shoot through the chairs
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, {[]{return true;}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM] = Region("Spirit Temple MQ Big Mirror Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);});}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE] = Region("Spirit Temple MQ Big Mirror Cave", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)),
}, {
//Exits
//If it's ever relevant to longshot into head from lobby, this needs to be an event access
Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE, []{return logic->CanUse(RG_MIRROR_SHIELD);}) && logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE, []{return logic->CanUse(RG_MIRROR_SHIELD);});}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD] = Region("Spirit Temple MQ Inside Statue Head", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
// Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, {[]{return true;} }),
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, {[]{return logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY);}}),
});
}
/*---------------------------

View File

@ -10,9 +10,9 @@ void RegionTable_Init_WaterTemple() {
---------------------------*/
areaTable[RR_WATER_TEMPLE_ENTRYWAY] = Region("Water Temple Entryway", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return logic->HasItem(RG_BRONZE_SCALE) && ctx->GetDungeon(WATER_TEMPLE)->IsVanilla();}}),
Entrance(RR_WATER_TEMPLE_MQ_LOBBY, {[]{return logic->HasItem(RG_BRONZE_SCALE) && ctx->GetDungeon(WATER_TEMPLE)->IsMQ();}}),
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return logic->HasItem(RG_BRONZE_SCALE) && ctx->GetDungeon(WATER_TEMPLE)->IsVanilla();}}),
Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, {[]{return logic->HasItem(RG_BRONZE_SCALE) && ctx->GetDungeon(WATER_TEMPLE)->IsMQ();}}),
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
});
/*--------------------------
@ -23,29 +23,29 @@ void RegionTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_LOBBY] = Region("Water Temple Lobby", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return logic->WaterTempleLow || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && (logic->CanUse(RG_IRON_BOOTS) || (logic->CanUse(RG_LONGSHOT) && ctx->GetTrickOption(RT_WATER_LONGSHOT_TORCH))));}}),
Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return logic->WaterTempleLow || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && logic->CanUse(RG_IRON_BOOTS));}}),
Entrance(RR_WATER_TEMPLE_SOUTH_LOWER, {[]{return logic->WaterTempleLow && logic->HasExplosives() && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)) && (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC));}}),
Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return logic->WaterTempleLow && logic->HasItem(RG_GORONS_BRACELET) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)) && (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC));}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return logic->WaterTempleLow && logic->SmallKeys(RR_WATER_TEMPLE, 5);}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER, {[]{return (logic->WaterTempleLow || logic->WaterTempleMiddle) && (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW));}}),
Entrance(RR_WATER_TEMPLE_EAST_MIDDLE, {[]{return (logic->WaterTempleLow || logic->WaterTempleMiddle || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16)) && logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_WEST_MIDDLE, {[]{return logic->WaterTempleMiddle;}}),
Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return logic->CanWaterTempleLowFromHigh || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && (logic->CanUse(RG_IRON_BOOTS) || (logic->CanUse(RG_LONGSHOT) && ctx->GetTrickOption(RT_WATER_LONGSHOT_TORCH))));}}),
Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return logic->CanWaterTempleLowFromHigh || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && logic->CanUse(RG_IRON_BOOTS));}}),
Entrance(RR_WATER_TEMPLE_SOUTH_LOWER, {[]{return logic->CanWaterTempleLowFromHigh && logic->HasExplosives() && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)) && (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC));}}),
Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return logic->CanWaterTempleLowFromHigh && logic->HasItem(RG_GORONS_BRACELET) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)) && (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC));}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return logic->CanWaterTempleLowFromHigh && logic->SmallKeys(RR_WATER_TEMPLE, 5);}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER, {[]{return (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle) && (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW));}}),
Entrance(RR_WATER_TEMPLE_EAST_MIDDLE, {[]{return (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16)) && logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_WEST_MIDDLE, {[]{return logic->CanWaterTempleMiddle;}}),
Entrance(RR_WATER_TEMPLE_HIGH_WATER, {[]{return logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DAMAGE_BOOST) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage()));}}),
Entrance(RR_WATER_TEMPLE_BLOCK_CORRIDOR, {[]{return (logic->WaterTempleLow || logic->WaterTempleMiddle) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW)) && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_WATER_CENTRAL_BOW) && (logic->IsAdult || logic->WaterTempleMiddle)));}}),
Entrance(RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM, {[]{return logic->WaterTempleHigh && logic->SmallKeys(RR_WATER_TEMPLE, 4);}}),
Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, {[]{return logic->WaterTempleHigh && logic->CanUse(RG_LONGSHOT);}}),
Entrance(RR_WATER_TEMPLE_BLOCK_CORRIDOR, {[]{return (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW)) && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_WATER_CENTRAL_BOW) && (logic->IsAdult || logic->CanWaterTempleMiddle)));}}),
Entrance(RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM, {[]{return logic->CanWaterTempleHigh && logic->SmallKeys(RR_WATER_TEMPLE, 4);}}),
Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, {[]{return logic->CanWaterTempleHigh && logic->CanUse(RG_LONGSHOT);}}),
});
areaTable[RR_WATER_TEMPLE_EAST_LOWER] = Region("Water Temple East Lower", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->WaterTempleLow, {[]{return logic->WaterTempleLow || logic->CanUse(RG_ZELDAS_LULLABY);}}),
EventAccess(&logic->CanWaterTempleLowFromHigh, {[]{return logic->CanWaterTempleLowFromHigh || logic->CanUse(RG_ZELDAS_LULLABY);}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return logic->WaterTempleLow || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && logic->CanUse(RG_IRON_BOOTS));}}),
Entrance(RR_WATER_TEMPLE_MAP_ROOM, {[]{return logic->WaterTempleHigh;}}),
Entrance(RR_WATER_TEMPLE_CRACKED_WALL, {[]{return logic->WaterTempleMiddle || (logic->WaterTempleHigh && logic->WaterTempleLow && ((logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_WATER_CRACKED_WALL_HOVERS)) || ctx->GetTrickOption(RT_WATER_CRACKED_WALL)));}}),
Entrance(RR_WATER_TEMPLE_TORCH_ROOM, {[]{return logic->WaterTempleLow && (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW));}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return logic->CanWaterTempleLowFromHigh || ((ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_ZORA_TUNIC)) && logic->CanUse(RG_IRON_BOOTS));}}),
Entrance(RR_WATER_TEMPLE_MAP_ROOM, {[]{return logic->CanWaterTempleHigh;}}),
Entrance(RR_WATER_TEMPLE_CRACKED_WALL, {[]{return logic->CanWaterTempleMiddle || (logic->CanWaterTempleHigh && logic->CanWaterTempleLowFromHigh && ((logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_WATER_CRACKED_WALL_HOVERS)) || ctx->GetTrickOption(RT_WATER_CRACKED_WALL)));}}),
Entrance(RR_WATER_TEMPLE_TORCH_ROOM, {[]{return logic->CanWaterTempleLowFromHigh && (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW));}}),
});
areaTable[RR_WATER_TEMPLE_MAP_ROOM] = Region("Water Temple Map Room", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -145,15 +145,15 @@ void RegionTable_Init_WaterTemple() {
//Exits
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return logic->SmallKeys(RR_WATER_TEMPLE, 5);}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER, {[]{return logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT, {[]{return logic->WaterTempleMiddle && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40;}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT, {[]{return logic->CanWaterTempleMiddle && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40;}}),
});
areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER] = Region("Water Temple Central Pillar Upper", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->WaterTempleMiddle, {[]{return logic->WaterTempleMiddle || logic->CanUse(RG_ZELDAS_LULLABY);}}),
EventAccess(&logic->CanWaterTempleMiddle, {[]{return logic->CanWaterTempleMiddle || logic->CanUse(RG_ZELDAS_LULLABY);}}),
}, {
//Locations
LOCATION(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, logic->CanUse(RG_LONGSHOT) || (((ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE) || logic->SmallKeys(RR_WATER_TEMPLE, 5))) || (ctx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && logic->CanUse(RG_IRON_BOOTS) && ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FAIRY_BOW)) || (logic->CanUse(RG_DINS_FIRE))))) && logic->WaterTempleHigh && logic->HookshotOrBoomerang())),
LOCATION(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, logic->CanUse(RG_LONGSHOT) || (((ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE) || logic->SmallKeys(RR_WATER_TEMPLE, 5))) || (ctx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && logic->CanUse(RG_IRON_BOOTS) && ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FAIRY_BOW)) || (logic->CanUse(RG_DINS_FIRE))))) && logic->CanWaterTempleHigh && logic->HookshotOrBoomerang())),
}, {
//Exits
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}),
@ -184,7 +184,7 @@ void RegionTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_HIGH_WATER] = Region("Water Temple High Water", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->WaterTempleHigh, {[]{return logic->WaterTempleHigh || logic->CanUse(RG_ZELDAS_LULLABY);}}),
EventAccess(&logic->CanWaterTempleHigh, {[]{return logic->CanWaterTempleHigh || logic->CanUse(RG_ZELDAS_LULLABY);}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}),
@ -192,7 +192,7 @@ void RegionTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_BLOCK_CORRIDOR] = Region("Water Temple Block Corridor", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, logic->HasItem(RG_GORONS_BRACELET) && (logic->WaterTempleLow || logic->WaterTempleMiddle)),
LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, logic->HasItem(RG_GORONS_BRACELET) && (logic->CanWaterTempleLowFromHigh || logic->CanWaterTempleMiddle)),
}, {
//Exits
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return logic->CanUse(RG_HOOKSHOT);}}),
@ -251,53 +251,407 @@ void RegionTable_Init_WaterTemple() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (ctx->GetDungeon(WATER_TEMPLE)->IsMQ()) {
areaTable[RR_WATER_TEMPLE_MQ_LOBBY] = Region("Water Temple MQ Lobby", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_MQ_3F_SOUTH_LEDGE] = Region("Water Temple MQ 3F South Ledge", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_DIVE, {[]{return logic->IsAdult && logic->WaterTimer() >= 24 && logic->CanUse(RG_IRON_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_MQ_DARK_LINK_REGION, {[]{return logic->SmallKeys(RR_WATER_TEMPLE, 1) && logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->CanJumpslashExceptHammer();}}),
Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, {[]{return logic->HasItem(RG_WATER_TEMPLE_BOSS_KEY) && logic->IsAdult && logic->CanJumpslashExceptHammer() && logic->CanUse(RG_LONGSHOT);}}),
Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return true;}}),
//If we are not on WL_HIGH, we reach RR_WATER_TEMPLE_MQ_3F_MAIN with hookshot via 2F, otherwise we can reach the platform
Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, {[]{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_MQ_2F_CENTRAL, {[]{return logic->MQWaterLevel(WL_LOW_OR_MID);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_DIVE] = Region("Water Temple MQ Dive", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_MAP_CHEST, logic->HasFireSource() && logic->IsAdult && logic->CanUse(RG_HOOKSHOT)),
LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, logic->IsAdult && logic->CanUse(RG_ZORA_TUNIC) && logic->CanUse(RG_HOOKSHOT) && ((ctx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS)) || (logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_SONG_OF_TIME)))),
//Trick: logic->IsAdult && logic->CanUse(RG_ZORA_TUNIC) && logic->CanUse(RG_HOOKSHOT) && ((LogicWaterMQCentralPillar && logic->CanUse(RG_FIRE_ARROWS)) || (logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_SONG_OF_TIME)))
//This region covers simply existing in the area around the central pillar without being on a specific platform, either swimming or walking on the lakebed
//Entry should only include being in the correct area, taking any possible fall damage, and floating up to the surface of WL_HIGH if coming from below
//This area then leads to others based on level and worst-case water timers for follow-up exits from the water's surface
//remember that any solution that works for any level doesn't need to be given a level, even if that solution is overkill for a lower level
areaTable[RR_WATER_TEMPLE_MQ_MAIN] = Region("Water Temple MQ Main", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_3F_SOUTH_LEDGE, {[]{return logic->HasItem(RG_BRONZE_SCALE) && logic->MQWaterLevel(WL_HIGH);}}),
//Jumping across is possible but a trick due to the janky ledge
Entrance(RR_WATER_TEMPLE_MQ_EAST_TOWER, {[]{return (logic->WaterTimer() >= 24 && logic->CanUse(RG_IRON_BOOTS)) ||
(logic->MQWaterLevel(WL_MID) && logic->HasItem(RG_GOLDEN_SCALE) && logic->WaterTimer() >= 16) ||
logic->MQWaterLevel(WL_LOW);}}),
Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, {[]{return logic->MQWaterLevel(WL_HIGH) && logic->HasItem(RG_BRONZE_SCALE);}}),
//First water timer uses the hook to go from the top of center to storage room/central pillar as coming from the bottom
//Second water timer is simply diving down and entering the door as fast as possible from the surface
Entrance(RR_WATER_TEMPLE_MQ_2F_CENTRAL, {[]{return ((logic->MQWaterLevel(WL_LOW) || (logic->CanUse(RG_IRON_BOOTS) && (logic->MQWaterLevel(WL_MID) || logic->WaterTimer() >= 16))) && logic->CanUse(RG_LONGSHOT)) ||
((logic->MQWaterLevel(WL_MID) || (logic->MQWaterLevel(WL_HIGH_OR_MID) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)) && logic->HasItem(RG_BRONZE_SCALE));}}),
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_1F, {[]{return logic->MQWaterLevel(WL_LOW);}}),
//A special entry as we can't set it to high after entering at a lower height
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH, {[]{return logic->MQWaterLevel(WL_HIGH) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT));}}),
Entrance(RR_WATER_TEMPLE_MQ_2F_SOUTH, {[]{return (logic->MQWaterLevel(WL_MID) || (logic->MQWaterLevel(WL_HIGH_OR_MID) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16)) && logic->HasItem(RG_BRONZE_SCALE);}}),
Entrance(RR_WATER_TEMPLE_MQ_B1_GATE_SWITCH, {[]{return logic->MQWaterB1Switch && (logic->MQWaterLevel(WL_LOW) || ((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24) && logic->HasItem(RG_BRONZE_SCALE)));}}),
Entrance(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM, {[]{return logic->MQWaterB1Switch &&
((logic->MQWaterLevel(WL_LOW) && logic->HasItem(RG_SILVER_SCALE)) ||
(logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT))));}}),
//Adult needs to jump in instead of dive for swim access, but you just hold forward. RT_WATER_BK_REGION Isn't relevant unless the Dark Link loop can be done without longshot with other tricks
Entrance(RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_ROOM, {[]{return logic->MQWaterB1Switch &&
((logic->MQWaterLevel(WL_LOW) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanUse(RG_HOOKSHOT))) &&
(logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_WATER_BK_REGION) && logic->CanUse(RG_HOVER_BOOTS)));}}),
});
//This region specifically covers the topmost platform around central pillar
areaTable[RR_WATER_TEMPLE_MQ_3F_CENTRAL] = Region("Water Temple MQ 3F Central", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_3F_SOUTH_LEDGE, {[]{return logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_MQ_2F_CENTRAL, {[]{return (logic->MQWaterLevel(WL_LOW_OR_MID) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16)) && logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH, {[]{return logic->MQWaterLevel(WL_HIGH) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_3F_NORTH_LEDGE, {[]{return logic->MQWaterLevel(WL_HIGH) && logic->CanUse(RG_LONGSHOT);}}),
//Jumping across is possible but a trick due to the janky ledge
Entrance(RR_WATER_TEMPLE_MQ_HIGH_EMBLEM, {[]{return logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS));}}),
//room access is (logic->IsAdult || (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)))
Entrance(RR_WATER_TEMPLE_MQ_WATERFALL, {[]{return logic->SmallKeys(RR_WATER_TEMPLE, 1) && logic->MQWaterLevel(WL_HIGH) && logic->CanUse(RG_LONGSHOT);}}),
//this swimless jump with irons may be a trick as you have to put irons on quite late.
Entrance(RR_WATER_TEMPLE_MQ_2F_SOUTH, {[]{return (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->MQWaterLevel(WL_LOW_OR_MID);}}),
});
//This region specifically covers walking on the lower platform around central pillar. This is underwater when WL_HIGH
//RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH should be accessed directly to use the central pillar door while at WL_HIGH
areaTable[RR_WATER_TEMPLE_MQ_2F_CENTRAL] = Region("Water Temple MQ 2F Central", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, {[]{return logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_2F, {[]{return logic->MQWaterLevel(WL_LOW_OR_MID);}}),
Entrance(RR_WATER_TEMPLE_MQ_STORAGE_ROOM, {[]{return logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_BEHIND_BLUE_SWITCH_2F, {[]{return logic->MQWaterLevel(WL_LOW_OR_MID) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_2F_SOUTH, {[]{return logic->MQWaterLevel(WL_LOW_OR_MID) && logic->CanUse(RG_HOVER_BOOTS);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_HIGH_EMBLEM] = Region("Water Temple MQ High Emblem", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->ReachedWaterHighEmblem, {[]{return true;}}),
EventAccess(&logic->CanWaterTempleHigh, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return true;}}),
});
areaTable[RR_WATER_TEMPLE_MQ_3F_NORTH_LEDGE] = Region("Water Temple MQ 3F North Ledge", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
//what we need if WL_LOW, we can't guarantee repeated access otherwise.
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return logic->HasItem(RG_BRONZE_SCALE) || logic->TakeDamage();}}),
Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, {[]{return logic->CanUse(RG_LONGSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_BOSS_DOOR, {[]{return logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_ICE_ARROWS) || logic->CanUse(RG_NAYRUS_LOVE);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_BOSS_DOOR] = Region("Water Temple MQ Main", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_3F_NORTH_LEDGE, {[]{return logic->CanUse(RG_ICE_ARROWS) || logic->TakeDamage();}}),
Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, {[]{return logic->HasItem(RG_WATER_TEMPLE_BOSS_KEY);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_EAST_TOWER] = Region("Water Temple MQ East Tower", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//if we can't reach these, we can't move the water at all, so no need to specify level or account for WL_LOW access here
//review is some way to play ocarina underwater exists
EventAccess(&logic->CouldWaterTempleLow, {[]{return true;}}),
EventAccess(&logic->CanWaterTempleLowFromHigh, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}),
//Reserved for glitches/tricks that could do this
//EventAccess(&logic->CanWaterTempleLowFromMid, {[]{return false;}}),
}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}),
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_MAP_CHEST, logic->MQWaterLevel(WL_HIGH) && logic->HasFireSource() && logic->CanUse(RG_HOOKSHOT)),
//easy to get at WL_HIGH with the hook-the-underwater-chest glitch
LOCATION(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, logic->MQWaterLevel(WL_MID) && logic->CanUse(RG_HOOKSHOT)),
}, {
Entrance(RR_WATER_TEMPLE_MQ_EAST_TOWER_1F_ROOM, {[]{return logic->MQWaterLevel(WL_LOW) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE) || logic->CanUse(RG_STICKS));}}),
});
areaTable[RR_WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS] = Region("Water Temple MQ Lowered Water Levels", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Raising the targets by clearing this room achieves nothing logically because it requires WL_LOW to do and hookshot to use, which implies access to WL_MID and WL_HIGH already
areaTable[RR_WATER_TEMPLE_MQ_EAST_TOWER_1F_ROOM] = Region("Water Temple MQ East Tower 1F Room", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, ((logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)) || logic->CanUse(RG_DINS_FIRE) || Here(RR_WATER_TEMPLE_MQ_LOBBY, []{return logic->IsChild && logic->CanUse(RG_STICKS) && logic->HasExplosives();})) &&
(logic->CanJumpslashExceptHammer() || logic->CanUseProjectile())),
LOCATION(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, logic->IsAdult && logic->CanUse(RG_HOOKSHOT)),
LOCATION(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, logic->CanUse(RG_DINS_FIRE)),
LOCATION(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, logic->IsAdult && logic->CanUse(RG_LONGSHOT)),
LOCATION(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_LIZALFOS) && logic->CanKillEnemy(RE_SPIKE)),
}, {
Entrance(RR_WATER_TEMPLE_MQ_EAST_TOWER, {[]{return true;}}),
});
//This area assumes we entered through the lower door, so water is low and cannot be changed without leaving.
areaTable[RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_1F] = Region("Water Temple MQ Central Pillar 1F", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//This is harder than the other possibilities as you have to move between shots on top of the extra range, but there's basically no universe this should matter.
EventAccess(&logic->MQWaterB1Switch, {[]{return ctx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS);}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH, {[]{return logic->MQWaterLevel(WL_HIGH) && ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && logic->HasItem(RG_BRONZE_SCALE);}}),
//I don't know if this FW trick can ever matter but maybe it's needed to get child to CENTRAL_2F or something
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_2F, {[]{return logic->CanUse(RG_HOOKSHOT) ||
(logic->MQWaterLevel(WL_MID) && ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) && logic->HasItem(RG_BRONZE_SCALE));}}),
//if the gate is open, you sink straight in, so you can't climb up this way in logic without swimming
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1, {[]{return logic->MQWaterOpenedPillarB1 && logic->MQWaterLevel(WL_HIGH_OR_MID) &&
ctx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && logic->CanUse(RG_FARORES_WIND) &&
logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_ZORA_TUNIC);}}),
});
//If we enter here in WL_HIGH, go to RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH instead, Assumes WL_MID_OR_LOW
areaTable[RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_2F] = Region("Water Temple MQ Central Pillar 2F", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->CouldWaterTempleMiddle, {[]{return true;}}),
EventAccess(&logic->CanWaterTempleMiddle, {[]{return logic->CanUse(RG_ZELDAS_LULLABY);}}),
//It's possible to do this even on low water, but more awkward. I'm not sure if it's even possible for it to be relevant though.
EventAccess(&logic->MQWaterOpenedPillarB1, {[]{return ctx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS);}}),
//this could theoretically matter once OI and equip swap is in logic, as one age may be able to get here dry and not wet, and the other may not be able to OI, but as you can OI with hookshot it probably never happens
//EventAccess(&logic->MQWaterPillarSoTBlock, {[]{return logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SONG_OF_TIME);}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH, {[]{return logic->MQWaterLevel(WL_HIGH) && logic->CanUse(RG_FARORES_WIND) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS));}}),
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1, {[]{return logic->MQWaterOpenedPillarB1 && logic->MQWaterLevel(WL_MID) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_ZORA_TUNIC);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH] = Region("Water Temple MQ Central Pillar High", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->MQWaterOpenedPillarB1, {[]{return ((logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_DINS_FIRE)) || (ctx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && logic->CanUse(RG_FIRE_ARROWS))) &&
(logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_LONGSHOT) && logic->CanJumpslash()));}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1, {[]{return logic->MQWaterB1Switch && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_ZORA_TUNIC);}}),
});
//Assuming tunic and irons was checked on entry
areaTable[RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1] = Region("Water Temple MQ Central Pillar B1", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
//Can't know water level, so we'll just assume any possibility and skip to MAIN
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return logic->MQWaterOpenedPillarB1 && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_BRONZE_SCALE);}}),
//Child needs to release irons for height to push down the larger "peg", however they can push the lower one down by climbing and then hit the switch through the larger peg, but it's a trick
Entrance(RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1_FINAL, {[]{return ((logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE)));}}),
});
areaTable[RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1_FINAL] = Region("Water Temple MQ Central Pillar B1 Final", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT)),
}, {});
areaTable[RR_WATER_TEMPLE_MQ_DARK_LINK_REGION] = Region("Water Temple MQ Dark Link Region", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Region exists to add crate/pot/box locations
areaTable[RR_WATER_TEMPLE_MQ_STORAGE_ROOM] = Region("Water Temple MQ Storage Room", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return logic->MQWaterLevel(WL_LOW_OR_MID) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_BEHIND_BLUE_SWITCH_2F] = Region("Water Temple MQ Behind Blue Switch 2F", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_BEHIND_BLUE_SWITCH_3F, {[]{return logic->CanUse(RG_LONGSHOT);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_BEHIND_BLUE_SWITCH_3F] = Region("Water Temple MQ Behind Blue Switch 2F", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)),
}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_BEHIND_BLUE_SWITCH_2F, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_HIGH_EMBLEM, {[]{return true;}}),
});
areaTable[RR_WATER_TEMPLE_MQ_2F_SOUTH] = Region("Water Temple MQ Lowered Water Levels", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_2F_SOUTH_CAGE, {[]{return logic->MQWaterLevel(WL_LOW_OR_MID) && logic->CanUse(RG_DINS_FIRE);}}),
//this technically exists, but only complicates things, uncomment if some edge case/glitch can use RR_WATER_TEMPLE_MQ_2F_SOUTH to reach RR_WATER_TEMPLE_MQ_3F_CENTRAL, or if a void warp goes here
/*Entrance(RR_WATER_TEMPLE_MQ_3F_EAST_LEDGE, {[]{return (logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS))) ||
(logic->MQWaterLevel(WL_LOW_OR_MID) && logic->CanUse(RG_HOOKSHOT)) ||
logic->MQWaterLevel(WL_HIGH) && (logic->HasItem(RG_BRONZE_SCALE));}}),
});
areaTable[RR_WATER_TEMPLE_MQ_3F_EAST_LEDGE] = Region("Water Temple MQ 3F East Ledge", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, {[]{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}}),*/
});
areaTable[RR_WATER_TEMPLE_MQ_2F_SOUTH_CAGE] = Region("Water Temple MQ Lowered Water Levels", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, logic->CanKillEnemy(RE_GOLD_SKULLTULA)),
}, {});
//This room exists to hold the wonderitems that drop from the emblems here. Specifically this assumes you are standing on the final ledge
areaTable[RR_WATER_TEMPLE_MQ_WATERFALL] = Region("Water Temple Waterfall", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, {[]{return logic->SmallKeys(RR_WATER_TEMPLE, 1) && logic->CanUse(RG_LONGSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS, {[]{return (logic->MQWaterStalfosPit && logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, {[]{return logic->MQWaterStalfosPit && logic->CanUse(RG_LONGSHOT);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_STALFOS_PIT] = Region("Water Temple MQ Stalfos Pit", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->MQWaterStalfosPit, {[]{return ((logic->IsAdult && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3, false, true)) ||
(logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->CanKillEnemy(RE_STALFOS, ED_BOMB_THROW, true, 3, false, true)));}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_WATERFALL, {[]{return logic->MQWaterStalfosPit && logic->CanUse(RG_HOOKSHOT) && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8);}}),
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS, {[]{return (logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) ||
(logic->CanUse(RG_HOOKSHOT) && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) && (logic->CanUse(RG_HOVER_BOOTS) || logic->MQWaterStalfosPit));}}),
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, {[]{return logic->MQWaterStalfosPit && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) && logic->CanUse(RG_HOOKSHOT);}}),
});
//also includes the suns fairy in the middle
areaTable[RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS] = Region("Water Temple MQ Stalfos Pit Pots", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->FairyPot, {[]{return true;}}),
EventAccess(&logic->NutPot, {[]{return true;}}),
}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, logic->IsAdult && logic->WaterTimer() >= 24 && logic->CanUse(RG_DINS_FIRE) && (ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE) || logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))),
LOCATION(RC_WATER_TEMPLE_MQ_GS_RIVER, true),
}, {
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS, {[]{return logic->IsAdult && logic->WaterTimer() >= 24 && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_IRON_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_MQ_WATERFALL, {[]{return logic->MQWaterStalfosPit && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT));}}),
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, {[]{return logic->MQWaterStalfosPit && logic->CanUse(RG_HOOKSHOT);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS] = Region("Water Temple MQ Basement Gated Areas", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//specifically the area past the spikes
areaTable[RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER] = Region("Water Temple MQ Stalfos Pit Upper", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT, {[]{return logic->IsAdult || logic->TakeDamage();}}),
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS, {[]{return logic->IsAdult || logic->TakeDamage();}}),
Entrance(RR_WATER_TEMPLE_MQ_AFTER_DARK_LINK, {[]{return logic->CanKillEnemy(RE_DARK_LINK);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_AFTER_DARK_LINK] = Region("Water Temple MQ After Dark Link", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->FairyPot, {[]{return true;}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, {[]{return logic->CanKillEnemy(RE_DARK_LINK);}}),
Entrance(RR_WATER_TEMPLE_MQ_RIVER_SKULL, {[]{return logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->CanUse(RG_LONGSHOT));}}),
});
//if we can use hookshot, we are standing on the targets, otherwise assume we're in the water
areaTable[RR_WATER_TEMPLE_MQ_RIVER_SKULL] = Region("Water Temple MQ River Skull", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SCARECROW) || ctx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP)),
LOCATION(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, logic->CanUse(RG_FIRE_ARROWS) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SCARECROW))),
LOCATION(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, ctx->GetTrickOption(RT_WATER_MQ_LOCKED_GS) || (logic->SmallKeys(RR_WATER_TEMPLE, 2) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SCARECROW) || ctx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP)) && logic->CanJumpslashExceptHammer())),
//Trick: LogicWaterMQLockedGS || (logic->SmallKeys(RR_WATER_TEMPLE, 2) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump))
LOCATION(RC_WATER_TEMPLE_MQ_GS_RIVER, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))),
}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_RIVER_POTS, {[]{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_RIVER_POTS] = Region("Water Temple MQ River Pots", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->FairyPot, {[]{return true;}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_RIVER_SKULL, {[]{return logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && logic->CanUse(RG_HOOKSHOT));}}),
//You don't need to swim for this if you put irons on in midair and hold forward while aiming for the tunnel with a tight angle, but if you miss you have to void unless you have a hook. It's only relevant with glitches anyway
Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL, {[]{return logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16;}}),
Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE, {[]{return logic->HasItem(RG_SILVER_SCALE) || (logic->IsAdult && logic->HasItem(RG_BRONZE_SCALE) && ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE));}}),
Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, {[]{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanJumpslash());}}),
});
//This region assumes Iron boots to access
areaTable[RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL] = Region("Water Temple MQ Dragon Room Tunnel", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_RIVER_POTS, {[]{return logic->CanUse(RG_LONGSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE, {[]{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, {[]{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE] = Region("Water Temple MQ Dragon Room Alcove", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->MQWaterDragonTorches, {[]{return true;}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL, {[]{return logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16;}}),
Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, {[]{return logic->HasItem(RG_SILVER_SCALE);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR] = Region("Water Temple MQ Dragon Room Door", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_RIVER_POTS, {[]{return logic->CanUse(RG_LONGSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL, {[]{return logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE, {[]{return logic->HasItem(RG_SILVER_SCALE);}}),
Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, {[]{return logic->MQWaterDragonTorches;}}),
});
areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH] = Region("Water Temple MQ Boss Key Room Switch", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_PIT, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, {[]{return logic->CanHitSwitch() && Here(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, []{return logic->CanUse(RG_DINS_FIRE);});}}),
});
//this exists for the crates in preparation for clips through the grate
areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_PIT] = Region("Water Temple MQ Boss Key Room Pit", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, {[]{return logic->CanHitSwitch(ED_BOOMERANG);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST] = Region("Water Temple MQ Boss Key Room Chest", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, true),
}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, {[]{return logic->CanHitSwitch(ED_BOMB_THROW) || logic->CanUse(RG_HOVER_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_PIT, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_B1_GATE_SWITCH, {[]{return logic->HasItem(RG_SILVER_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && (logic->HasItem(RG_BRONZE_SCALE) || (logic->WaterTimer() >= 24 && logic->CanUse(RG_LONGSHOT))));}}),
});
areaTable[RR_WATER_TEMPLE_MQ_B1_GATE_SWITCH] = Region("Water Temple MQ B1 Gate Switch", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//If the water is low, the switch is underwater and needs irons to press, otherwise, the water is too low to climb up and you need irons to hookshot a target
//If a glitch clips through the gate on low, have it logically press the switch and let entrance logic enter
EventAccess(&logic->MQWaterB1Switch, {[]{return logic->CanUse(RG_IRON_BOOTS);}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return logic->MQWaterB1Switch && (logic->MQWaterLevel(WL_LOW) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16));}}),
Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, {[]{return logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && (logic->MQWaterLevel(WL_LOW) || logic->WaterTimer() >= 24);}})
});
areaTable[RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM] = Region("Water Temple MQ Triangle Torch Room", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return logic->MQWaterB1Switch &&
((logic->MQWaterLevel(WL_LOW) && logic->HasItem(RG_GOLDEN_SCALE)) ||
(logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT))));}}),
Entrance(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_CAGE, {[]{return logic->CanUse(RG_FIRE_ARROWS) &&
((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || (logic->CanUse(RG_LONGSHOT) && Here(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_CAGE, []{return logic->ScarecrowsSong();})));}})
});
areaTable[RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_CAGE] = Region("Water Temple MQ Triangle Torch Cage", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
}, {});
areaTable[RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_ROOM] = Region("Water Temple MQ Crates Whirlpools Room", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
//we can backflip over the spikes, but land in water.
Entrance(RR_WATER_TEMPLE_MQ_MAIN, {[]{return logic->MQWaterB1Switch && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && (logic->CanUse(RG_LONGSHOT) || logic->HasItem(RG_BRONZE_SCALE));}}),
//Child can use the crate to get the height to make it with hovers, but it's annoyingly tight so would be a trick
Entrance(RR_WATER_TEMPLE_MQ_SINGLE_STALFOS_ROOM, {[]{return logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 &&
//We're putting the requirement to get out of the water here as the scarecrow method in includes hook which satisfies it
((logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP)) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BRONZE_SCALE))) ||
(Here(RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_ROOM, []{return logic->ScarecrowsSong();}) && logic->CanUse(RG_HOOKSHOT)));}}),
Entrance(RR_WATER_TEMPLE_MQ_4_TORCH_ROOM, {[]{return logic->IsAdult &&
(logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP) ||
(Here(RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_ROOM, []{return logic->ScarecrowsSong();}) && logic->CanUse(RG_HOOKSHOT)));}}),
Entrance(RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_CAGE, {[]{return ctx->GetTrickOption(RT_WATER_MQ_LOCKED_GS) && (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT));}}),
});
areaTable[RR_WATER_TEMPLE_MQ_SINGLE_STALFOS_ROOM] = Region("Water Temple MQ Single Stalfos Room", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, true),
}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_ROOM, {[]{return logic->HasItem(RG_SILVER_SCALE) || (logic->IsChild && logic->HasItem(RG_BRONZE_SCALE)) ||
(logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT)));}})
});
areaTable[RR_WATER_TEMPLE_MQ_4_TORCH_ROOM] = Region("Water Temple MQ 4 Torch Room", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_ROOM, {[]{return (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash())) ||
(logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && logic->CanUse(RG_HOOKSHOT) ));}}),
Entrance(RR_WATER_TEMPLE_MQ_DODONGO_ROOM, {[]{return logic->CanHitSwitch() && logic->HasFireSource();}})
});
areaTable[RR_WATER_TEMPLE_MQ_DODONGO_ROOM] = Region("Water Temple MQ Dodongo Room", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_MQ_4_TORCH_ROOM, {[]{return (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)) &&
Here(RR_WATER_TEMPLE_MQ_DODONGO_ROOM, []{return logic->CanKillEnemy(RE_DODONGO, ED_CLOSE, true, 5);});}}),
Entrance(RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_CAGE, {[]{return (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)) &&
Here(RR_WATER_TEMPLE_MQ_DODONGO_ROOM, []{return logic->CanKillEnemy(RE_DODONGO, ED_CLOSE, true, 5);});}})
});
areaTable[RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_CAGE] = Region("Water Temple MQ Basement Gated Areas", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)),
}, {
Entrance(RR_WATER_TEMPLE_MQ_DODONGO_ROOM, {[]{return true;}})
});
}
/*---------------------------
@ -307,9 +661,9 @@ void RegionTable_Init_WaterTemple() {
Region("Water Temple Boss Entryway", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, { [] { return ctx->GetDungeon(WATER_TEMPLE)->IsVanilla() && false; } }),
Entrance(RR_WATER_TEMPLE_MQ_LOBBY, { [] { return ctx->GetDungeon(WATER_TEMPLE)->IsMQ() && false; } }),
Entrance(RR_WATER_TEMPLE_BOSS_ROOM, { [] { return true; } }),
Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, {[]{return ctx->GetDungeon(WATER_TEMPLE)->IsVanilla() && false;}}),
Entrance(RR_WATER_TEMPLE_MQ_BOSS_DOOR, {[]{return ctx->GetDungeon(WATER_TEMPLE)->IsMQ() && false;}}),
Entrance(RR_WATER_TEMPLE_BOSS_ROOM, {[]{return true;}}),
});
areaTable[RR_WATER_TEMPLE_BOSS_ROOM] = Region("Water Temple Boss Room", "Water Temple", {}, NO_DAY_NIGHT_CYCLE,

View File

@ -923,7 +923,7 @@ int EntranceShuffler::ShuffleAllEntrances() {
{ EntranceType::Interior, RR_MARKET_POTION_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_TREASURE_CHEST_GAME, ENTR_TREASURE_BOX_SHOP_0 },
{ EntranceType::Interior, RR_MARKET_TREASURE_CHEST_GAME, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP } },
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_0 },
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1 },
{ EntranceType::Interior, RR_MARKET_BOMBCHU_SHOP, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP } },
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE },
{ EntranceType::Interior, RR_MARKET_MAN_IN_GREEN_HOUSE, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE } },

View File

@ -829,7 +829,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
Actor_Kill(&item00->actor);
*should = false;
} else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY) {
Audio_PlaySoundGeneral(NA_SE_SY_GET_ITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GET_ITEM, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
if (item00->itemEntry.modIndex == MOD_NONE) {
if (item00->itemEntry.getItemId == GI_SWORD_BGS) {
gSaveContext.bgsFlag = true;

View File

@ -59,6 +59,7 @@ namespace Rando {
case RG_PROGRESSIVE_NUT_UPGRADE:
case RG_NUTS:
return CurrentUpgrade(UPG_NUTS);
//RANDOTODO handle cases where the scarecrow is persistent between age better when OI is added
case RG_SCARECROW:
return ScarecrowsSong() && CanUse(RG_HOOKSHOT);
case RG_DISTANT_SCARECROW:
@ -433,12 +434,15 @@ namespace Rando {
case ED_LONG_JUMPSLASH:
killed = killed || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS);
[[fallthrough]];
case ED_BOMB_THROW:
killed = killed || CanUse(RG_BOMB_BAG);
[[fallthrough]];
case ED_BOOMERANG:
//RANDOTODO test dins, bomb and chu range in a practical example
killed = killed || CanUse(RG_BOMB_BAG) || CanUse(RG_DINS_FIRE);
//RANDOTODO test dins and chu range in a practical example
killed = killed || CanUse(RG_DINS_FIRE);
[[fallthrough]];
case ED_HOOKSHOT:
//RANDOTODO test dins, bomb and chu range in a practical example
//RANDOTODO test dins and chu range in a practical example
killed = killed || CanUse(RG_HOOKSHOT) || (wallOrFloor && CanUse(RG_BOMBCHU_5));
[[fallthrough]];
case ED_LONGSHOT:
@ -450,6 +454,7 @@ namespace Rando {
}
return killed;
case RE_DODONGO:
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || (quantity <= 5 && CanUse(RG_STICKS)) || HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
case RE_LIZALFOS:
return CanJumpslash() || HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
case RE_KEESE:
@ -465,9 +470,13 @@ namespace Rando {
case ED_LONG_JUMPSLASH:
killed = killed || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS);
[[fallthrough]];
case ED_BOMB_THROW:
//RANDOTODO test dins and chu range in a practical example
killed = killed || (!inWater && CanUse(RG_BOMB_BAG));
[[fallthrough]];
case ED_BOOMERANG:
//RANDOTODO test dins, bomb and chu range in a practical example
killed = killed || CanUse(RG_BOOMERANG) || (!inWater && CanUse(RG_BOMB_BAG));
//RANDOTODO test dins and chu range in a practical example
killed = killed || CanUse(RG_BOOMERANG);
[[fallthrough]];
case ED_HOOKSHOT:
//RANDOTODO test dins, bomb and chu range in a practical example
@ -495,8 +504,31 @@ namespace Rando {
return CanDamage();
case RE_STALFOS:
//RANDOTODO Add trick to kill stalfos with sticks, and a second one for bombs without stunning. Higher ammo logic for bombs is also plausible
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_FAIRY_BOW) || CanUse(RG_BOMBCHU_5) ||
(quantity <= 2 && !timer && (CanUse(RG_NUTS) || HookshotOrBoomerang()) && CanUse(RG_BOMB_BAG)) || (quantity <= 1 && CanUse(RG_STICKS));
switch (distance){
case ED_CLOSE:
case ED_SHORT_JUMPSLASH:
killed = CanUse(RG_MEGATON_HAMMER) || CanUse(RG_KOKIRI_SWORD);
[[fallthrough]];
case ED_MASTER_SWORD_JUMPSLASH:
killed = killed || CanUse(RG_MASTER_SWORD);
[[fallthrough]];
case ED_LONG_JUMPSLASH:
killed = killed || CanUse(RG_BIGGORON_SWORD) || (quantity <= 1 && CanUse(RG_STICKS));
[[fallthrough]];
case ED_BOMB_THROW:
killed = killed || (quantity <= 2 && !timer && !inWater && (CanUse(RG_NUTS) || HookshotOrBoomerang()) && CanUse(RG_BOMB_BAG));
[[fallthrough]];
case ED_BOOMERANG:
case ED_HOOKSHOT:
//RANDOTODO test dins and chu range in a practical example
killed = killed || (wallOrFloor && CanUse(RG_BOMBCHU_5));
[[fallthrough]];
case ED_LONGSHOT:
case ED_FAR:
killed = killed || CanUse(RG_FAIRY_BOW);
break;
}
return killed;
//Needs 16 bombs, but is in default logic in N64, probably because getting the hits is quite easy.
//bow and sling can wake them and damage after they shed their armour, so could reduce ammo requirements for explosives to 10.
//requires 8 sticks to kill so would be a trick unless we apply higher stick bag logic
@ -510,6 +542,7 @@ namespace Rando {
return CanUse(RG_MEGATON_HAMMER) || CanUse(RG_HOOKSHOT) || (HasExplosives() && (CanJumpslashExceptHammer() || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG)));
case RE_WOLFOS:
case RE_WHITE_WOLFOS:
case RE_WALLMASTER:
return CanJumpslash() || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOMBCHU_5) || CanUse(RG_DINS_FIRE) || (CanUse(RG_BOMB_BAG) && (CanUse(RG_NUTS) || CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG)));
case RE_GIBDO:
case RE_REDEAD:
@ -543,10 +576,11 @@ namespace Rando {
case ED_LONG_JUMPSLASH:
killed = killed || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS);
[[fallthrough]];
case ED_BOOMERANG:
//RANDOTODO test dins, bomb and chu range in a practical example
case ED_BOMB_THROW:
//RANDOTODO test dins and chu range in a practical example
killed = killed || (!inWater && CanUse(RG_BOMB_BAG));
[[fallthrough]];
case ED_BOOMERANG:
case ED_HOOKSHOT:
//RANDOTODO test dins, bomb and chu range in a practical example
killed = killed || CanUse(RG_HOOKSHOT) || (wallOrFloor && CanUse(RG_BOMBCHU_5));
@ -562,6 +596,30 @@ namespace Rando {
case RE_BIG_OCTO:
//If chasing octo is annoying but with rolls you can catch him, and you need rang to get into this room without shenanigains anyway. Bunny makes it free
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_STICKS) || CanUse(RG_MASTER_SWORD);
case RE_GANONDORF:
// RANDOTODO: Trick to use hammer (no jumpslash) or stick (only jumpslash) instead of a sword to reflect the energy ball
// and either of them regardless of jumpslashing to damage and kill ganondorf
// Bottle is not taken into account since a sword, hammer or stick are required
// for killing ganondorf and all of those can reflect the energy ball
// This will not be the case once ammo logic in taken into account as
// sticks are limited and using a bottle might become a requirement in that case
return HasBossSoul(RG_GANON_SOUL) && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD));
case RE_GANON:
return HasBossSoul(RG_GANON_SOUL) && CanUse(RG_MASTER_SWORD);
case RE_DARK_LINK:
//RANDOTODO Dark link is buggy right now, retest when he is not
return CanJumpslash() || CanUse(RG_FAIRY_BOW);
case RE_ANUBIS:
//there's a restoration that allows beating them with mirror shield + some way to trigger thier attack
return HasFireSource();
case RE_BEAMOS:
return HasExplosives();
case RE_PURPLE_LEEVER:
//dies on it's own, so this is the conditions to spawn it (killing 10 normal leevers)
//Sticks and Ice arrows work but will need ammo capacity logic
//other mothods can damage them but not kill them, and they run when hit, making them impractical
return CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);
default:
SPDLOG_ERROR("CanKillEnemy reached `default`.");
assert(false);
@ -597,6 +655,10 @@ namespace Rando {
case RE_ARMOS:
case RE_FREEZARD:
case RE_SPIKE:
case RE_DARK_LINK:
case RE_ANUBIS:
case RE_WALLMASTER:
case RE_PURPLE_LEEVER:
return true;
case RE_BIG_SKULLTULA:
//hammer jumpslash can pass, but only on flat land where you can kill with hammer swing
@ -620,47 +682,56 @@ namespace Rando {
}
//Can we avoid this enemy while climbing up a wall, or doing a difficult platforming challenge?
bool Logic::CanAvoidEnemy(RandomizerEnemy enemy) {
if (CanKillEnemy(enemy)){
return true;
}
switch(enemy) {
case RE_GOLD_SKULLTULA:
case RE_GOHMA_LARVA:
case RE_LIZALFOS:
case RE_DODONGO: //RANDOTODO do dodongos block the way in tight corridors?
case RE_BIG_SKULLTULA:
case RE_DEAD_HAND:
case RE_DEKU_BABA:
case RE_WITHERED_DEKU_BABA:
case RE_LIKE_LIKE:
case RE_STALFOS:
case RE_IRON_KNUCKLE:
case RE_FLARE_DANCER:
case RE_WOLFOS:
case RE_WHITE_WOLFOS:
case RE_FLOORMASTER:
case RE_REDEAD:
case RE_MEG:
case RE_ARMOS:
case RE_GREEN_BUBBLE:
case RE_FREEZARD:
case RE_SPIKE:
case RE_BIG_OCTO:
case RE_GIBDO:
return true;
case RE_MAD_SCRUB:
case RE_KEESE:
case RE_FIRE_KEESE:
return CanUse(RG_NUTS);
case RE_BLUE_BUBBLE:
//RANDOTODO Trick to use shield hylian shield as child to stun these guys
return CanUse(RG_NUTS) || HookshotOrBoomerang() || CanStandingShield();
default:
SPDLOG_ERROR("CanPassEnemy reached `default`.");
assert(false);
return false;
}
//use grounded if the challenge is such that the enemy interfears even if it cannot hit link out of the air
bool Logic::CanAvoidEnemy(RandomizerEnemy enemy, bool grounded, uint8_t quantity) {
//DISTANCE AND WALL ASSUMED, add more arguments later if needed
if (CanKillEnemy(enemy, ED_CLOSE, true, quantity)){
return true;
}
switch(enemy) {
case RE_GOLD_SKULLTULA:
case RE_GOHMA_LARVA:
case RE_LIZALFOS:
case RE_DODONGO:
case RE_BIG_SKULLTULA:
case RE_DEAD_HAND:
case RE_DEKU_BABA:
case RE_WITHERED_DEKU_BABA:
case RE_LIKE_LIKE:
case RE_STALFOS:
case RE_IRON_KNUCKLE:
case RE_FLARE_DANCER:
case RE_WOLFOS:
case RE_WHITE_WOLFOS:
case RE_FLOORMASTER:
case RE_REDEAD:
case RE_MEG:
case RE_ARMOS:
case RE_GREEN_BUBBLE:
case RE_FREEZARD:
case RE_SPIKE:
case RE_BIG_OCTO:
case RE_GIBDO:
case RE_DARK_LINK:
case RE_WALLMASTER:
case RE_ANUBIS:
case RE_PURPLE_LEEVER:
return true;
case RE_BEAMOS:
return !grounded || CanUse(RG_NUTS) || (quantity == 1 && (CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT)));
case RE_MAD_SCRUB:
return !grounded || CanUse(RG_NUTS);
case RE_KEESE:
case RE_FIRE_KEESE:
return CanUse(RG_NUTS);
case RE_BLUE_BUBBLE:
//RANDOTODO Trick to use shield hylian shield as child to stun these guys
return !grounded || CanUse(RG_NUTS) || HookshotOrBoomerang() || CanStandingShield();
default:
SPDLOG_ERROR("CanPassEnemy reached `default`.");
assert(false);
return false;
}
}
bool Logic::CanGetEnemyDrop(RandomizerEnemy enemy, EnemyDistance distance, bool aboveLink) {
@ -678,6 +749,7 @@ namespace Rando {
case ED_SHORT_JUMPSLASH:
case ED_MASTER_SWORD_JUMPSLASH:
case ED_LONG_JUMPSLASH:
case ED_BOMB_THROW:
case ED_BOOMERANG:
drop = drop || CanUse(RG_BOOMERANG);
[[fallthrough]];
@ -688,9 +760,10 @@ namespace Rando {
drop = drop || CanUse(RG_LONGSHOT);
[[fallthrough]];
case ED_FAR:
return drop;
break;
//RANDOTODO double check all jumpslash kills that might be out of jump/backflip range
}
return drop;
break;
case RE_KEESE:
case RE_FIRE_KEESE:
@ -725,6 +798,35 @@ namespace Rando {
return CanDetonateBombFlowers() || HasItem(RG_GORONS_BRACELET);
}
bool Logic::MQWaterLevel(RandoWaterLevel level) {
//For ease of reading, I will call the triforce emblem that sets the water to WL_LOW the "Low Emblem", the one that sets it to WL_MID the "Mid Emblem", and the one that sets it to WL_HIGH the "High Emblem"
switch(level){
//While you have to go through WL_LOW to get to Mid, the requirements for WL_LOW are stricter than WL_MID because you can always go up to WL_MID and then could need to go back to WL_HIGH to reach the Low Emblem again
//Thanks to this caveat you need to be able to reach and play ZL to both the High and Low Emblems to have WL_LOW in logic.
//Alternativly a way to reach WL_LOW from WL_MID could exist, but all glitchless methods need you to do a Low-locked action
case WL_LOW:
return (CanWaterTempleHigh && CanWaterTempleLowFromHigh) || (CanWaterTempleLowFromMid && CanWaterTempleLowFromHigh);
case WL_LOW_OR_MID:
return (CanWaterTempleHigh && CanWaterTempleLowFromHigh) || (CanWaterTempleLowFromHigh && CanWaterTempleMiddle) || (CanWaterTempleLowFromMid && CanWaterTempleLowFromHigh);
//If we can set it to High out of logic we can just repeat what we did to lower the water in the first place as High is the default.
//Because of this you only need to be able to use the Low and Mid Emblems, WL_LOW could be skipped if it was ever possible to play ZL underwater.
case WL_MID:
return CanWaterTempleLowFromHigh && CanWaterTempleMiddle;
//Despite being the initial state of water temple, WL_HIGH has the extra requirement of making sure that, if we were to lower the water out of logic, we could put it back to WL_HIGH
//However because it is the default state, we do not need to check if we can actually change the water level, only to make sure we can return to WL_HIGH if we found the means to play ZL out of logic.
//There are 2 methods to lock yourself out after playing ZL already: Not being able to reach the High Emblem and being unable to replay ZL. (I will be ignoring other-age-access shenanigains)
//The former check would simply be a check to see if we can reach High Emblem, but we assume the water is WL_MID (as if we can set it to WL_LOW, we can set it to WL_MID, as Mid Emblem has no requirements)
//The latter check can be assumed for now but will want a revisit once OI tricks are added.
case WL_HIGH:
return ReachedWaterHighEmblem;
case WL_HIGH_OR_MID:
return ReachedWaterHighEmblem || (CanWaterTempleLowFromHigh && CanWaterTempleMiddle);
}
SPDLOG_ERROR("MQWaterLevel reached `return false;`. Missing case for a Water Level");
assert(false);
return false;
}
Logic::Logic() {
}
@ -773,12 +875,14 @@ namespace Rando {
case ED_LONG_JUMPSLASH:
hit = hit || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS);
[[fallthrough]];
case ED_BOMB_THROW:
hit = hit || (!inWater && CanUse(RG_BOMB_BAG));
[[fallthrough]];
case ED_BOOMERANG:
//RANDOTODO test bomb and chu range in a practical example
hit = hit || CanUse(RG_BOOMERANG) || (!inWater && CanUse(RG_BOMB_BAG)) ;
hit = hit || CanUse(RG_BOOMERANG);
[[fallthrough]];
case ED_HOOKSHOT:
//RANDOTODO test bomb and chu range in a practical example
//RANDOTODO test chu range in a practical example
hit = hit || CanUse(RG_HOOKSHOT) || CanUse(RG_BOMBCHU_5) ;
[[fallthrough]];
case ED_LONGSHOT:
@ -2007,9 +2111,10 @@ namespace Rando {
GCWoodsWarpOpen = false;
GCDaruniasDoorOpenChild = false;
StopGCRollingGoronAsAdult = false;
WaterTempleLow = false;
WaterTempleMiddle = false;
WaterTempleHigh = false;
CanWaterTempleLowFromHigh = false;
CanWaterTempleLowFromMid = false;
CanWaterTempleMiddle = false;
CanWaterTempleHigh = false;
KakarikoVillageGateOpen = false;
KingZoraThawed = false;
ForestTempleJoelle = false;
@ -2045,6 +2150,14 @@ namespace Rando {
MQJabuLiftRoomCow = false;
MQShadowFloorSpikeRupees = false;
ShadowShortcutBlock = false;
MQWaterStalfosPit = false;
MQWaterDragonTorches = false;
MQWaterB1Switch = false;
//MQWaterPillarSoTBlock = false;
MQWaterOpenedPillarB1 = false;
MQSpiritCrawlBoulder = false;
MQSpiritMapRoomEnemies = false;
MQSpirit3SunsEnemies = false;
StopPerformanceTimer(PT_LOGIC_RESET);
}

View File

@ -118,9 +118,13 @@ class Logic {
bool GCWoodsWarpOpen = false;
bool GCDaruniasDoorOpenChild = false;
bool StopGCRollingGoronAsAdult = false;
bool WaterTempleLow = false;
bool WaterTempleMiddle = false;
bool WaterTempleHigh = false;
bool CanWaterTempleLowFromHigh = false;
bool CanWaterTempleMiddle = false;
bool CanWaterTempleHigh = false;
bool CanWaterTempleLowFromMid = false;
bool CouldWaterTempleLow = false;
bool CouldWaterTempleMiddle = false;
bool ReachedWaterHighEmblem = false;
bool KakarikoVillageGateOpen = false;
bool KingZoraThawed = false;
bool ForestTempleJoelle = false;
@ -157,6 +161,16 @@ class Logic {
bool MQJabuLiftRoomCow = false;
bool MQShadowFloorSpikeRupees = false;
bool ShadowShortcutBlock = false;
bool MQWaterStalfosPit = false;
bool MQWaterDragonTorches = false;
bool MQWaterB1Switch = false;
//bool MQWaterPillarSoTBlock = false; should be irrelevant. SHOULD.
bool MQWaterOpenedPillarB1 = false;
bool MQSpiritCrawlBoulder = false;
bool MQSpiritMapRoomEnemies = false;
bool MQSpiritTimeTravelChest = false;
bool MQSpirit3SunsEnemies = false;
bool Spirit1FSilverRupees = false;
/* --- END OF HELPERS AND LOCATION ACCESS --- */
@ -172,7 +186,7 @@ class Logic {
bool CanEquipSwap(RandomizerGet itemName);
bool CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool wallOrFloor = true, uint8_t quantity = 1, bool timer = false, bool inWater = false);
bool CanPassEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool wallOrFloor = true);
bool CanAvoidEnemy(RandomizerEnemy enemy);
bool CanAvoidEnemy(RandomizerEnemy enemy, bool grounded = false, uint8_t quantity = 1);
bool CanGetEnemyDrop(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool aboveLink = false);
bool CanBreakMudWalls();
bool CanGetDekuBabaSticks();
@ -180,6 +194,7 @@ class Logic {
bool CanHitEyeTargets();
bool CanDetonateBombFlowers();
bool CanDetonateUprightBombFlower();
bool MQWaterLevel(RandoWaterLevel level);
uint8_t BottleCount();
uint8_t OcarinaButtons();
bool HasBottle();

View File

@ -751,11 +751,48 @@ typedef enum {
RR_WATER_TEMPLE_RIVER,
RR_WATER_TEMPLE_PRE_BOSS_ROOM,
RR_WATER_TEMPLE_MQ_LOBBY,
RR_WATER_TEMPLE_MQ_DIVE,
RR_WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS,
RR_WATER_TEMPLE_MQ_DARK_LINK_REGION,
RR_WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS,
RR_WATER_TEMPLE_MQ_3F_SOUTH_LEDGE,
RR_WATER_TEMPLE_MQ_MAIN,
RR_WATER_TEMPLE_MQ_3F_CENTRAL,
RR_WATER_TEMPLE_MQ_2F_CENTRAL,
RR_WATER_TEMPLE_MQ_2F_CENTRAL_HIGH,
RR_WATER_TEMPLE_MQ_HIGH_EMBLEM,
RR_WATER_TEMPLE_MQ_3F_NORTH_LEDGE,
RR_WATER_TEMPLE_MQ_BOSS_DOOR,
RR_WATER_TEMPLE_MQ_EAST_TOWER,
RR_WATER_TEMPLE_MQ_EAST_TOWER_1F_ROOM,
RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_1F,
RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_2F,
RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_HIGH,
RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1,
RR_WATER_TEMPLE_MQ_CENTRAL_PILLAR_B1_FINAL,
RR_WATER_TEMPLE_MQ_BEHIND_BLUE_SWITCH_2F,
RR_WATER_TEMPLE_MQ_BEHIND_BLUE_SWITCH_3F,
RR_WATER_TEMPLE_MQ_STORAGE_ROOM,
RR_WATER_TEMPLE_MQ_2F_SOUTH,
RR_WATER_TEMPLE_MQ_2F_SOUTH_CAGE,
RR_WATER_TEMPLE_MQ_3F_EAST_LEDGE,
RR_WATER_TEMPLE_MQ_WATERFALL,
RR_WATER_TEMPLE_MQ_STALFOS_PIT,
RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS,
RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER,
RR_WATER_TEMPLE_MQ_AFTER_DARK_LINK,
RR_WATER_TEMPLE_MQ_RIVER_SKULL,
RR_WATER_TEMPLE_MQ_RIVER_POTS,
RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR,
RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL,
RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE,
RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH,
RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_PIT,
RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST,
RR_WATER_TEMPLE_MQ_B1_GATE_SWITCH,
RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM,
RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_CAGE,
RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_ROOM,
RR_WATER_TEMPLE_MQ_SINGLE_STALFOS_ROOM,
RR_WATER_TEMPLE_MQ_4_TORCH_ROOM,
RR_WATER_TEMPLE_MQ_DODONGO_ROOM,
RR_WATER_TEMPLE_MQ_CRATES_WHIRLPOOLS_CAGE,
RR_WATER_TEMPLE_BOSS_ENTRYWAY,
RR_WATER_TEMPLE_BOSS_ROOM,
@ -771,13 +808,39 @@ typedef enum {
RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD,
RR_SPIRIT_TEMPLE_MQ_LOBBY,
RR_SPIRIT_TEMPLE_MQ_CHILD,
RR_SPIRIT_TEMPLE_MQ_ADULT,
RR_SPIRIT_TEMPLE_MQ_SHARED,
RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT,
RR_SPIRIT_TEMPLE_MQ_BOSS_AREA,
RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND,
RR_SPIRIT_TEMPLE_MQ_1F_WEST,
RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_NORTH,
RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_SOUTH,
RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM,
RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_NORTH,
RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH,
RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH,
RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE,
RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM,
RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM,
RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM,
RR_SPIRIT_TEMPLE_MQ_WEST_IRON_KNUCKLE,
RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND,
RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH,
RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH,
RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST,
RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F,
RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F,
RR_SPIRIT_TEMPLE_MQ_1F_EAST,
RR_SPIRIT_TEMPLE_MQ_LEEVER_ROOM,
RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM,
RR_SPIRIT_TEMPLE_MQ_AFTER_SYMPHONY_ROOM,
RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM,
RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM,
RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND,
RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE,
RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND,
RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM,
RR_SPIRIT_TEMPLE_MQ_BIG_WALL,
RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL,
RR_SPIRIT_TEMPLE_MQ_NINE_CHAIRS_ROOM,
RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM,
RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE,
RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD,
RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY,
@ -888,7 +951,6 @@ typedef enum {
RR_GANONS_CASTLE_SHADOW_TRIAL,
RR_GANONS_CASTLE_SPIRIT_TRIAL,
RR_GANONS_CASTLE_LIGHT_TRIAL,
RR_GANONS_CASTLE_TOWER,
RR_GANONS_CASTLE_MQ_LOBBY,
RR_GANONS_CASTLE_MQ_MAIN,
@ -917,6 +979,13 @@ typedef enum {
RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_BOULDER_ROOM_BACK,
RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_FINAL_ROOM,
RR_GANONS_TOWER_FLOOR_1,
RR_GANONS_TOWER_FLOOR_2,
RR_GANONS_TOWER_FLOOR_3,
RR_GANONS_TOWER_GANONDORF_LAIR,
RR_GANONS_CASTLE_ESCAPE,
RR_GANONS_CASTLE_GANON_ARENA,
RR_MARKER_AREAS_END, // Used for area key count
// DUNGEONS
@ -4525,6 +4594,13 @@ typedef enum {
RE_STINGER,
RE_BIG_OCTO,
RE_GIBDO,
RE_GANONDORF,
RE_GANON,
RE_DARK_LINK,
RE_ANUBIS,
RE_BEAMOS,
RE_WALLMASTER,
RE_PURPLE_LEEVER,
} RandomizerEnemy;
//RANDOTODO compare child long jumpslash range with adult short
@ -4535,12 +4611,21 @@ typedef enum {
ED_MASTER_SWORD_JUMPSLASH,
//sticks or BGS
ED_LONG_JUMPSLASH,
ED_BOMB_THROW,
ED_BOOMERANG,
ED_HOOKSHOT,
ED_LONGSHOT,
ED_FAR,
} EnemyDistance;
typedef enum {
WL_LOW,
WL_MID,
WL_HIGH,
WL_LOW_OR_MID,
WL_HIGH_OR_MID
} RandoWaterLevel;
#define ENTRANCE_GROTTO_LOAD_START 0x0700
#define ENTRANCE_GROTTO_EXIT_START 0x0800

View File

@ -198,7 +198,7 @@ void Entrance_Init(void) {
bossSceneSaveDeathWarps[bossScene - SCENE_DEKU_TREE_BOSS] = saveWarpEntrance;
}
//Overwrite grotto related indices
// Overwrite grotto related indices
if (originalIndex >= ENTRANCE_GROTTO_EXIT_START) {
Grotto_SetExitOverride(originalIndex, overrideIndex);
continue;
@ -226,7 +226,7 @@ void Entrance_Init(void) {
s16 indicesToSilenceBackgroundMusic[2] = {
// The lost woods music playing near the GC Woods Warp keeps playing
// in the next area if the bvackground music is allowed to keep playing
// in the next area if the background music is allowed to keep playing
entranceOverrideTable[ENTR_LOST_WOODS_TUNNEL_SHORTCUT], // Goron City -> Lost Woods override
// If Malon is singing at night, then her singing will be transferred
@ -452,7 +452,19 @@ void Entrance_SetWarpSongEntrance(void) {
}
void Entrance_OverrideBlueWarp(void) {
// Handles first time entering bluewarp (with item give)
// Remap child 2nd visits in adult dungeons for warp pad -> bluewarp
if (gSaveContext.entranceIndex == ENTR_SACRED_FOREST_MEADOW_WARP_PAD) {
gSaveContext.entranceIndex = ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP;
} else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD) {
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP;
} else if (gSaveContext.entranceIndex == ENTR_LAKE_HYLIA_WARP_PAD) {
gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP;
} else if (gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_WARP_PAD) {
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP;
} else if (gSaveContext.entranceIndex == ENTR_GRAVEYARD_WARP_PAD) {
gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP;
}
switch (gSaveContext.entranceIndex) {
case ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP: // Gohma blue warp
case ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP: // KD blue warp
@ -465,20 +477,6 @@ void Entrance_OverrideBlueWarp(void) {
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(gSaveContext.entranceIndex);
return;
}
// Handles second+ times entering bluewarp
switch (gPlayState->nextEntranceIndex) {
case ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP: // Gohma blue warp
case ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP: // KD blue warp
case ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP: // Barinade blue warp
case ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP: // Phantom Ganon blue warp
case ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP: // Volvagia blue warp
case ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP: // Morpha blue warp
case ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP: // Bongo-Bongo blue warp
case ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP: // Twinrova blue warp
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(gPlayState->nextEntranceIndex);
return;
}
}
void Entrance_EnableFW(void) {

View File

@ -99,6 +99,10 @@ void Grotto_InitExitAndLoadLists(void) {
grottoLoadList[i] = ENTRANCE_GROTTO_LOAD_START + i;
grottoExitList[i] = ENTRANCE_GROTTO_EXIT_START + i;
}
grottoId = 0xFF;
lastEntranceType = NOT_GROTTO;
overridingNextEntrance = false;
}
void Grotto_SetExitOverride(s16 originalIndex, s16 overrideIndex) {

View File

@ -445,6 +445,7 @@ void Settings::CreateOptions() {
mTrickOptions[RT_WATER_BK_REGION] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, false, "Water Temple Boss Key Region with Hover Boots", "With precise Hover Boots movement it is possible to reach the boss key chest's region without needing the Longshot. It is not necessary to take damage from the spikes. The Gold Skulltula Token in the following room can also be obtained with just the Hover Boots.");
mTrickOptions[RT_WATER_NORTH_BASEMENT_LEDGE_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, false, "Water Temple North Basement Ledge with Precise Jump", "In the northern basement there's a ledge from where, in vanilla Water Temple, boulders roll out into the room. Normally to jump directly to this ledge logically requires the Hover Boots, but with precise jump, it can be done without them. This trick applies to both Vanilla and Master Quest.");
mTrickOptions[RT_WATER_BK_JUMP_DIVE] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, false, "Water Temple Boss Key Jump Dive", "Stand on the very edge of the raised corridor leading from the push block room to the rolling boulder corridor. Face the gold skulltula on the waterfall and jump over the boulder corridor floor into the pool of water, swimming right once underwater. This allows access to the boss key room without Iron boots.");
//Also used in MQ logic, but won't be relevent unless a way to enter tower without irons exists (likely a clip + swim)
mTrickOptions[RT_WATER_FW_CENTRAL_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, false, "Water Temple Central Pillar GS with Farore\'s Wind", "If you set Farore's Wind inside the central pillar and then return to that warp point after raising the water to the highest level, you can obtain this Skulltula Token with Hookshot or Boomerang.");
mTrickOptions[RT_WATER_IRONS_CENTRAL_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, false, "Water Temple Central Pillar GS with Iron Boots", "After opening the middle water level door into the central pillar, the door will stay unbarred so long as you do not leave the room -- even if you were to raise the water up to the highest level. With the Iron Boots to go through the door after the water has been raised, you can obtain the Skulltula Token with the Hookshot.");
mTrickOptions[RT_WATER_CENTRAL_BOW] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::ADVANCED}, false, "Water Temple Central Bow Target without Longshot or Hover Boots", "A very precise Bow shot can hit the eye switch from the floor above. Then, you can jump down into the hallway and make through it before the gate closes. It can also be done as child, using the Slingshot instead of the Bow.");

View File

@ -14,6 +14,7 @@ extern "C" {
#include "src/overlays/actors/ovl_En_Owl/z_en_owl.h"
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
#include "src/overlays/actors/ovl_En_Ma1/z_en_ma1.h"
#include "src/overlays/actors/ovl_En_Ru2/z_en_ru2.h"
#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
#include "src/overlays/actors/ovl_En_Box/z_en_box.h"
#include "src/overlays/actors/ovl_Demo_Im/z_demo_im.h"
@ -33,6 +34,8 @@ extern "C" {
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
extern int32_t D_8011D3AC;
extern void func_80AF36EC(EnRu2* enRu2, PlayState* play);
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex()
@ -40,7 +43,7 @@ extern int32_t D_8011D3AC;
void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) {
if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) {
Flags_SetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG);
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
enMa1->actor.flags &= ~ACTOR_FLAG_WILL_TALK;
play->msgCtx.ocarinaMode = OCARINA_MODE_04;
enMa1->actionFunc = func_80AA0D88;
@ -52,7 +55,7 @@ void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) {
void EnFu_EndTeachSong(EnFu* enFu, PlayState* play) {
if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) {
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
enFu->actionFunc = EnFu_WaitAdult;
enFu->actor.flags &= ~ACTOR_FLAG_WILL_TALK;
@ -427,7 +430,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
player->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM;
if (Animation_OnFrame(&demoIm->skelAnime, 25.0f)) {
Audio_PlaySoundGeneral(NA_SE_IT_DEKU, &demoIm->actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_DEKU, &demoIm->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(demoImUpdateHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(demoImKillHook);
demoImUpdateHook = 0;
@ -506,7 +509,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
*should = false;
Flags_SetEnv(gPlayState, 2);
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
}
break;
}
@ -813,6 +816,15 @@ void TimeSaverOnActorInitHandler(void* actorRef) {
Actor_Kill(actor);
}
}
// Water Temple Ruto cutscene
if (actor->id == ACTOR_EN_RU2 && gPlayState->sceneNum == SCENE_WATER_TEMPLE) {
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
EnRu2* enRu2 = (EnRu2*)actor;
func_80AF36EC(enRu2, gPlayState);
Actor_Kill(actor);
}
}
}
void TimeSaverOnSceneInitHandler(int16_t sceneNum) {

View File

@ -181,7 +181,7 @@ void RegisterOnInterfaceUpdateHook() {
if (gPlayState->state.frames % 7 == 0) {
if (lostHealth >= 16) {
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
lostHealth -= 16;
}
}

View File

@ -133,7 +133,7 @@ void Emit(Options notification) {
notification.remainingTime = CVarGetFloat(CVAR_SETTING("Notifications.Duration"), 10.0f);
}
notifications.push_back(notification);
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} // namespace Notification

View File

@ -1743,7 +1743,7 @@ void DrawCheatsMenu() {
UIWidgets::EnhancementSliderFloat("Hookshot Reach Multiplier: %.2fx", "##gCheatHookshotReachMultiplier", CVAR_CHEAT("HookshotReachMultiplier"), 1.0f, 5.0f, "", 1.0f, false);
UIWidgets::Spacer(2.0f);
if (ImGui::Button("Change Age")) {
CVarSetInteger(CVAR_GENERAL("SwitchAge"), 1);
SwitchAge();
}
UIWidgets::Tooltip("Switches Link's age and reloads the area.");
UIWidgets::Spacer(2.0f);

View File

@ -23,6 +23,10 @@ u16 gAudioSEFlagSwapSource[64];
u16 gAudioSEFlagSwapTarget[64];
u8 gAudioSEFlagSwapMode[64];
// Zbuffer and Color framebuffer
u16 D_0E000000[SCREEN_WIDTH * SCREEN_HEIGHT];
u16 D_0F000000[SCREEN_WIDTH * SCREEN_HEIGHT];
u8 osAppNmiBuffer[2048];
f32 qNaN0x10000 = 0x7F810000;

View File

@ -19,19 +19,19 @@ Ship::IResource* OTRPlay_LoadFile(PlayState* play, const char* fileName)
return res.get();
}
extern "C" void OTRPlay_SpawnScene(PlayState* play, s32 sceneNum, s32 spawn) {
SceneTableEntry* scene = &gSceneTable[sceneNum];
extern "C" void OTRPlay_SpawnScene(PlayState* play, s32 sceneId, s32 spawn) {
SceneTableEntry* scene = &gSceneTable[sceneId];
scene->unk_13 = 0;
play->loadedScene = scene;
play->sceneNum = sceneNum;
play->sceneNum = sceneId;
play->sceneConfig = scene->config;
//osSyncPrintf("\nSCENE SIZE %fK\n", (scene->sceneFile.vromEnd - scene->sceneFile.vromStart) / 1024.0f);
// Scenes considered "dungeon" with a MQ variant
int16_t inNonSharedScene = (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_ICE_CAVERN) ||
sceneNum == SCENE_GERUDO_TRAINING_GROUND || sceneNum == SCENE_INSIDE_GANONS_CASTLE;
int16_t inNonSharedScene = (sceneId >= SCENE_DEKU_TREE && sceneId <= SCENE_ICE_CAVERN) ||
sceneId == SCENE_GERUDO_TRAINING_GROUND || sceneId == SCENE_INSIDE_GANONS_CASTLE;
std::string sceneVersion = "shared";
if (inNonSharedScene) {

View File

@ -1,97 +0,0 @@
#include "global.h"
// Note : This file is related to z_vismono, the original name was probably z_vis<something before "mono"
// alphabetically>
Gfx D_8012AC00[] = {
gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | G_RM_VISCVG | G_RM_VISCVG2),
gsDPFillRectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1),
gsDPPipeSync(),
gsDPSetBlendColor(0, 0, 0, 8),
gsSPEndDisplayList(),
};
Gfx D_8012AC28[] = {
gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL |
GBL_c1(G_BL_CLR_FOG, G_BL_A_FOG, G_BL_CLR_MEM, G_BL_A_MEM) |
GBL_c2(G_BL_CLR_FOG, G_BL_A_FOG, G_BL_CLR_MEM, G_BL_A_MEM)),
gsDPFillRectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1),
gsSPEndDisplayList(),
};
Gfx D_8012AC40[] = {
gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL |
GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_MEM, G_BL_A_MEM) |
GBL_c2(G_BL_CLR_IN, G_BL_0, G_BL_CLR_MEM, G_BL_A_MEM)),
gsDPFillRectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1),
gsSPEndDisplayList(),
};
Gfx D_8012AC58[] = {
gsDPSetCombineMode(G_CC_PRIMITIVE, G_CC_PRIMITIVE),
gsDPSetOtherMode(G_AD_NOTPATTERN | G_CD_DISABLE | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | G_RM_CLD_SURF | G_RM_CLD_SURF2),
gsDPFillRectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1),
gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL |
GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_MEM, G_BL_A_MEM) |
GBL_c2(G_BL_CLR_IN, G_BL_0, G_BL_CLR_MEM, G_BL_A_MEM)),
gsDPFillRectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1),
gsSPEndDisplayList(),
};
// Init
void func_800ACE70(struct_801664F0* this) {
this->type = 0;
this->setScissor = false;
this->color.r = 255;
this->color.g = 255;
this->color.b = 255;
this->color.a = 255;
}
// Destroy
void func_800ACE90(struct_801664F0* this) {
}
// Draw
void func_800ACE98(struct_801664F0* this, Gfx** gfxp) {
Gfx* gfx = *gfxp;
gDPPipeSync(gfx++);
gDPSetPrimDepth(gfx++, -1, -1);
if (this->setScissor == true) {
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
switch (this->type) {
case 1:
gSPDisplayList(gfx++, D_8012AC40);
break;
case 2:
gDPSetColor(gfx++, G_SETPRIMCOLOR, this->color.rgba);
gSPDisplayList(gfx++, D_8012AC58);
break;
case 3:
gDPSetColor(gfx++, G_SETBLENDCOLOR, this->color.rgba);
gSPDisplayList(gfx++, D_8012AC00);
break;
case 4:
gDPSetColor(gfx++, G_SETFOGCOLOR, this->color.rgba);
gSPDisplayList(gfx++, D_8012AC28);
break;
}
gDPPipeSync(gfx++);
*gfxp = gfx;
}

View File

@ -1,64 +0,0 @@
#include "global.h"
// Note : This file is related to z_vismono, the original name was probably z_vis<something after "mono" alphabetically>
// z-buffer
extern u16 D_0E000000[];
// Init
void func_800AD920(struct_80166500* this) {
this->useRgba = false;
this->setScissor = false;
this->primColor.r = 255;
this->primColor.g = 255;
this->primColor.b = 255;
this->primColor.a = 255;
this->envColor.a = 255;
this->envColor.r = 0;
this->envColor.g = 0;
this->envColor.b = 0;
}
// Destroy
void func_800AD950(struct_80166500* this) {
}
// Draw
void func_800AD958(struct_80166500* this, Gfx** gfxp) {
Gfx* gfx = *gfxp;
// OTRTODO
#if 0
u16* tex = D_0E000000;
s32 fmt = this->useRgba == false ? G_IM_FMT_IA : G_IM_FMT_RGBA;
s32 y;
s32 height = 6;
gDPPipeSync(gfx++);
if (this->setScissor == true) {
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
gDPSetOtherMode(gfx++,
G_AD_DISABLE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | G_RM_OPA_SURF | G_RM_OPA_SURF2);
gDPSetCombineLERP(gfx++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT,
PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT);
gDPSetColor(gfx++, G_SETPRIMCOLOR, this->primColor.rgba);
gDPSetColor(gfx++, G_SETENVCOLOR, this->envColor.rgba);
for (y = 0; y <= SCREEN_HEIGHT - height; y += height) {
gDPLoadTextureBlock(gfx++, tex, fmt, G_IM_SIZ_16b, SCREEN_WIDTH, height, 0, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gSPTextureRectangle(gfx++, 0, (y) << 2, (SCREEN_WIDTH << 2), (y + height) << 2, G_TX_RENDERTILE, 0, 0,
(1 << 10), (1 << 10));
tex += SCREEN_WIDTH * height;
}
gDPPipeSync(gfx++);
*gfxp = gfx;
#endif
}

View File

@ -1648,7 +1648,7 @@ void func_800ED458(s32 arg0) {
if ((sCurOcarinaBtnVal != 0xFF) && (sPrevOcarinaNoteVal != sCurOcarinaBtnVal)) {
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | 0xD07, D_80130F10 - 1);
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | 0xD05, sCurOcarinaBtnVal);
Audio_PlaySoundGeneral(NA_SE_OC_OCARINA, &D_801333D4, 4, &D_80130F24, &D_80130F28, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_OC_OCARINA, &gSfxDefaultPos, 4, &D_80130F24, &D_80130F28, &gSfxDefaultReverb);
} else if ((sPrevOcarinaNoteVal != 0xFF) && (sCurOcarinaBtnVal == 0xFF)) {
Audio_StopSfxById(NA_SE_OC_OCARINA);
}
@ -1791,8 +1791,8 @@ void Audio_OcaPlayback(void) {
sStaffPlaybackPos++;
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | 0xD07, D_80130F10 - 1);
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | 0xD05, sDisplayedNoteValue & 0x3F);
Audio_PlaySoundGeneral(NA_SE_OC_OCARINA, &D_801333D4, 4, &sNormalizedNotePlaybackTone,
&sNormalizedNotePlaybackVolume, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_OC_OCARINA, &gSfxDefaultPos, 4, &sNormalizedNotePlaybackTone,
&sNormalizedNotePlaybackVolume, &gSfxDefaultReverb);
} else {
Audio_StopSfxById(NA_SE_OC_OCARINA);
}
@ -3044,7 +3044,7 @@ void AudioDebug_ProcessInput_SndCont(void) {
case 2:
case 3:
Audio_PlaySoundGeneral(((sAudioSndContWork[2] << 12) & 0xFFFF) + sAudioSndContWork[3] + SFX_FLAG,
&D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
&gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break;
case 4:
func_800F6700(sAudioSndContWork[sAudioSndContSel]);
@ -3443,7 +3443,7 @@ void AudioDebug_ProcessInput_SfxParamChg(void) {
if (CHECK_BTN_ANY(sDebugPadPress, BTN_A)) {
sfx = (u16)(sAudioSfxParamChgWork[0] << 12) + sAudioSfxParamChgWork[1] + SFX_FLAG;
Audio_PlaySoundGeneral(sfx, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(sfx, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
if (CHECK_BTN_ANY(sDebugPadPress, BTN_B)) {
@ -3974,7 +3974,7 @@ void Audio_PlayFanfare_Rando(GetItemEntry getItem) {
if (getItem.modIndex == MOD_NONE) {
if (((itemId >= ITEM_RUPEE_GREEN) && (itemId <= ITEM_RUPEE_GOLD)) || (itemId == ITEM_HEART)) {
Audio_PlaySoundGeneral(NA_SE_SY_GET_BOXITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GET_BOXITEM, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
if (itemId == ITEM_HEART_CONTAINER ||
((itemId == ITEM_HEART_PIECE_2) && ((gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000))) {
@ -4046,7 +4046,7 @@ void func_800F4010(Vec3f* pos, u16 sfxId, f32 arg2) {
D_80131C8C = arg2;
sp24 = func_800F3F84(arg2);
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_8016B7B0, &D_8016B7A8, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_8016B7B0, &D_8016B7A8, &gSfxDefaultReverb);
if ((sfxId & 0xF0) == 0xB0) {
phi_f0 = 0.3f;
@ -4064,22 +4064,22 @@ void func_800F4010(Vec3f* pos, u16 sfxId, f32 arg2) {
sfxId2 = NA_SE_PL_METALEFFECT_KID;
}
D_8016B7AC = (sp24 * 0.7) + 0.3;
Audio_PlaySoundGeneral(sfxId2, pos, 4, &D_8016B7B0, &D_8016B7AC, &D_801333E8);
Audio_PlaySoundGeneral(sfxId2, pos, 4, &D_8016B7B0, &D_8016B7AC, &gSfxDefaultReverb);
}
}
void func_800F4138(Vec3f* pos, u16 sfxId, f32 arg2) {
func_800F3F84(arg2);
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_8016B7B0, &D_8016B7A8, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_8016B7B0, &D_8016B7A8, &gSfxDefaultReverb);
}
void func_800F4190(Vec3f* pos, u16 sfxId) {
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_801305B0, &D_801333E0, &D_801305B4);
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_801305B0, &gSfxDefaultFreqAndVolScale, &D_801305B4);
}
void Audio_PlaySoundRandom(Vec3f* pos, u16 baseSfxId, u8 randLim) {
u8 offset = Audio_NextRandom() % randLim;
Audio_PlaySoundGeneral(baseSfxId + offset, pos, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(baseSfxId + offset, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
void func_800F4254(Vec3f* pos, u8 level) {
@ -4088,10 +4088,10 @@ void func_800F4254(Vec3f* pos, u8 level) {
D_801305F4 = D_801305E4[level];
switch (level) {
case 1:
Audio_PlaySoundGeneral(NA_SE_PL_SWORD_CHARGE, pos, 4, &D_801305F4, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_PL_SWORD_CHARGE, pos, 4, &D_801305F4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break;
case 2:
Audio_PlaySoundGeneral(NA_SE_PL_SWORD_CHARGE, pos, 4, &D_801305F4, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_PL_SWORD_CHARGE, pos, 4, &D_801305F4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break;
}
@ -4099,7 +4099,7 @@ void func_800F4254(Vec3f* pos, u8 level) {
}
if (level != 0) {
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_CHARGE - SFX_FLAG, pos, 4, &D_801305F4, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_CHARGE - SFX_FLAG, pos, 4, &D_801305F4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
@ -4111,14 +4111,14 @@ void func_800F436C(Vec3f* pos, u16 sfxId, f32 arg2) {
}
if (D_8016B7D8 > 0.5f) {
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_8016B7D8, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_8016B7D8, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
void func_800F4414(Vec3f* pos, u16 sfxId, f32 arg2) {
D_801305B8--;
if (D_801305B8 == 0) {
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_8016B7D8, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_8016B7D8, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
if (arg2 > 2.0f) {
arg2 = 2.0f;
@ -4135,17 +4135,17 @@ void func_800F44EC(s8 arg0, s8 arg1) {
void func_800F4524(Vec3f* pos, u16 sfxId, s8 arg2) {
D_8016B7DC = arg2;
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_801333E0, &D_801333E0, &D_8016B7DC);
Audio_PlaySoundGeneral(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &D_8016B7DC);
}
void func_800F4578(Vec3f* pos, u16 sfxId, f32 arg2) {
D_8016B7E0 = arg2;
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_801333E0, &D_8016B7E0, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &D_8016B7E0, &gSfxDefaultReverb);
}
void func_800F45D0(f32 arg0) {
func_800F4414(&D_801333D4, NA_SE_IT_FISHING_REEL_SLOW - SFX_FLAG, arg0);
func_800F436C(&D_801333D4, 0, (0.15f * arg0) + 1.4f);
func_800F4414(&gSfxDefaultPos, NA_SE_IT_FISHING_REEL_SLOW - SFX_FLAG, arg0);
func_800F436C(&gSfxDefaultPos, 0, (0.15f * arg0) + 1.4f);
}
void Audio_PlaySoundRiver(Vec3f* pos, f32 freqScale) {
@ -4156,8 +4156,8 @@ void Audio_PlaySoundRiver(Vec3f* pos, f32 freqScale) {
sRiverFreqScaleLerp.remainingFrames = 40;
sRiverFreqScaleLerp.step = (sRiverFreqScaleLerp.target - sRiverFreqScaleLerp.value) / 40;
}
Audio_PlaySoundGeneral(NA_SE_EV_RIVER_STREAM - SFX_FLAG, pos, 4, &sRiverFreqScaleLerp.value, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_RIVER_STREAM - SFX_FLAG, pos, 4, &sRiverFreqScaleLerp.value, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
void Audio_PlaySoundWaterfall(Vec3f* pos, f32 freqScale) {
@ -4169,7 +4169,7 @@ void Audio_PlaySoundWaterfall(Vec3f* pos, f32 freqScale) {
sWaterfallFreqScaleLerp.step = (sWaterfallFreqScaleLerp.target - sWaterfallFreqScaleLerp.value) / 40;
}
Audio_PlaySoundGeneral(NA_SE_EV_WATER_WALL_BIG - SFX_FLAG, pos, 4, &sWaterfallFreqScaleLerp.value,
&sWaterfallFreqScaleLerp.value, &D_801333E8);
&sWaterfallFreqScaleLerp.value, &gSfxDefaultReverb);
}
void Audio_StepFreqLerp(FreqLerp* lerp) {
@ -4285,8 +4285,8 @@ void func_800F4A70(void) {
}
void Audio_PlaySoundIncreasinglyTransposed(Vec3f* pos, s16 sfxId, u8* semitones) {
Audio_PlaySoundGeneral(sfxId, pos, 4, &gNoteFrequencies[semitones[sAudioIncreasingTranspose] + 39], &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(sfxId, pos, 4, &gNoteFrequencies[semitones[sAudioIncreasingTranspose] + 39], &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
if (sAudioIncreasingTranspose < 15) {
sAudioIncreasingTranspose++;
@ -4298,7 +4298,7 @@ void Audio_ResetIncreasingTranspose(void) {
}
void Audio_PlaySoundTransposed(Vec3f* pos, u16 sfxId, s8 semitone) {
Audio_PlaySoundGeneral(sfxId, pos, 4, &gNoteFrequencies[semitone + 39], &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, pos, 4, &gNoteFrequencies[semitone + 39], &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
void func_800F4C58(Vec3f* pos, u16 sfxId, u8 arg2) {
@ -4319,7 +4319,7 @@ void func_800F4C58(Vec3f* pos, u16 sfxId, u8 arg2) {
}
phi_s1++;
}
Audio_PlaySoundGeneral(sfxId, pos, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
void func_800F4E30(Vec3f* pos, f32 arg1) {
@ -4880,10 +4880,10 @@ void func_800F6268(f32 dist, u16 arg1) {
void func_800F64E0(u8 arg0) {
D_80130608 = arg0;
if (arg0 != 0) {
Audio_PlaySoundGeneral(NA_SE_SY_WIN_OPEN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_WIN_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Audio_QueueCmdS32(0xF1000000, 0);
} else {
Audio_PlaySoundGeneral(NA_SE_SY_WIN_CLOSE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_WIN_CLOSE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Audio_QueueCmdS32(0xF2000000, 0);
}
}
@ -4961,7 +4961,7 @@ void Audio_SetBaseFilter(u8 filter) {
if (filter == 0) {
Audio_StopSfxById(NA_SE_PL_IN_BUBBLE);
} else if (sAudioBaseFilter == 0) {
Audio_PlaySoundGeneral(NA_SE_PL_IN_BUBBLE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_PL_IN_BUBBLE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
sAudioBaseFilter = filter;
@ -4994,7 +4994,7 @@ void Audio_PlaySoundGeneralIfNotInCutscene(u16 sfxId, Vec3f* pos, u8 arg2, f32*
}
void Audio_PlaySoundIfNotInCutscene(u16 sfxId) {
Audio_PlaySoundGeneralIfNotInCutscene(sfxId, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneralIfNotInCutscene(sfxId, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
void func_800F6964(u16 arg0) {

View File

@ -81,13 +81,13 @@ u8 gSfxChannelLayout = 0;
u16 D_801333D0 = 0;
Vec3f D_801333D4 = { 0.0f, 0.0f, 0.0f }; // default pos
Vec3f gSfxDefaultPos = { 0.0f, 0.0f, 0.0f }; // default pos
f32 D_801333E0 = 1.0f; // default freqScale
f32 gSfxDefaultFreqAndVolScale = 1.0f; // default freqScale
s32 D_801333E4 = 0; // unused
s8 D_801333E8 = 0; // default reverbAdd
s8 gSfxDefaultReverb = 0; // default reverbAdd
s32 D_801333EC = 0; // unused
@ -381,7 +381,7 @@ void Audio_ChooseActiveSounds(u8 bankId)
} else if (gSoundBanks[bankId][entryIndex].state != SFX_STATE_EMPTY) {
entry = &gSoundBanks[bankId][entryIndex];
if (&D_801333D4.x == entry[0].posX) {
if (&gSfxDefaultPos.x == entry[0].posX) {
entry->dist = 0.0f;
} else {
tempf1 = *entry->posY * 1;

View File

@ -294,7 +294,7 @@ void func_800B44E0(DbCamera* dbCamera, Camera* cam) {
if (dbCamera->sub.nPoints < 6) {
if (sDbCamAnim.unk_0A != 0) {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
sDbCamAnim.unk_0A = 0;
}
func_8006376C(0x0D, 0x17, 3, cameraStrings[0]);
@ -308,7 +308,7 @@ void func_800B44E0(DbCamera* dbCamera, Camera* cam) {
!func_800BB2B4(&sDbCamAnim.lookAtPos, &sDbCamAnim.roll, &sDbCamAnim.fov, dbCamera->sub.lookAt,
&sDbCamAnim.keyframe, &sDbCamAnim.curFrame) &&
sDbCamAnim.unk_0A == 1) {
Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
sDbCamAnim.unk_04++;
if (dbCamera->sub.nFrames > 0 && dbCamera->sub.nFrames < sDbCamAnim.unk_04) {
@ -536,7 +536,7 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
dbCamera->unk_40 = -1;
dbCamera->sub.demoCtrlActionIdx = 0;
sDbCamAnim.unk_0A = 0;
Audio_PlaySoundGeneral(NA_SE_SY_LOCK_ON, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_LOCK_ON, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else if (dbCamera->unk_38 == -1) {
dbCamera->unk_38 = 1;
} else {
@ -856,22 +856,22 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
dbCamera->unk_1C.z = 0.0f;
dbCamera->unk_1C.y = 1.0f;
} else if (dbCamera->sub.unk_08 == 2) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
dbCamera->sub.unk_08 = 0;
func_800B41DC(dbCamera, dbCamera->sub.unkIdx, cam);
} else {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_R) &&
CHECK_BTN_ALL(sPlayState->state.input[2].cur.button, BTN_L)) {
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
dbCamera->sub.nPoints = dbCamera->sub.unkIdx + 1;
func_800B4088(dbCamera, cam);
} else if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_R)) {
if (dbCamera->sub.unkIdx == 0x80) {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_PUTAWAY, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_PUTAWAY, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
func_800B42C0(dbCamera, cam);
if (dbCamera->sub.unkIdx == (dbCamera->sub.nPoints - 1)) {
dbCamera->sub.unkIdx++;
@ -923,7 +923,7 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
} else {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_CRIGHT) &&
CHECK_BTN_ALL(sPlayState->state.input[2].cur.button, BTN_L)) {
Audio_PlaySoundGeneral(NA_SE_SY_GET_RUPY, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GET_RUPY, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
osSyncPrintf("@@@\n@@@\n@@@/* *** spline point data ** start here *** */\n@@@\n");
DbCamera_PrintPoints("Lookat", dbCamera->sub.nPoints, dbCamera->sub.lookAt);
DbCamera_PrintPoints("Position", dbCamera->sub.nPoints, dbCamera->sub.position);
@ -932,13 +932,13 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
osSyncPrintf("@@@static short Mode = %d;\n@@@\n", dbCamera->sub.mode);
osSyncPrintf("@@@\n@@@\n@@@/* *** spline point data ** finish! *** */\n@@@\n");
} else if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_CLEFT)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
dbCamera->sub.unk_08 = (dbCamera->sub.unk_08 + 1) % 3;
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_CUP) &&
CHECK_BTN_ALL(sPlayState->state.input[2].cur.button, BTN_L)) {
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_IMPACT, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_IMPACT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
if (dbCamera->sub.unkIdx > 0) {
dbCamera->sub.unkIdx--;
} else {
@ -946,8 +946,8 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
}
} else {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_CUP)) {
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_IMPACT, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_IMPACT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
if (dbCamera->sub.unkIdx > 0) {
dbCamera->sub.unkIdx--;
} else {
@ -968,7 +968,7 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].cur.button, BTN_L) &&
CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_CDOWN)) {
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_IMPACT, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_IMPACT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
if (dbCamera->sub.unkIdx < (dbCamera->sub.nPoints - 1)) {
dbCamera->sub.unkIdx++;
} else {
@ -976,8 +976,8 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
}
} else {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_CDOWN)) {
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_IMPACT, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_IMPACT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
if (dbCamera->sub.unkIdx < (dbCamera->sub.nPoints - 1)) {
dbCamera->sub.unkIdx++;
} else {
@ -1046,8 +1046,8 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
case 1:
dbCamera->unk_3C = true;
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DUP)) {
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
if (dbCamera->sub.unk_0A == 0) {
dbCamera->sub.unk_0A = 5;
} else {
@ -1055,8 +1055,8 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
}
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DDOWN)) {
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
if (dbCamera->sub.unk_0A == 5) {
dbCamera->sub.unk_0A = 0;
} else {
@ -1064,8 +1064,8 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
}
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DLEFT)) {
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
switch (dbCamera->sub.unk_0A) {
case 1:
if (CHECK_BTN_ALL(sPlayState->state.input[2].cur.button, BTN_L)) {
@ -1114,8 +1114,8 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
if (CHECK_BTN_ALL(sPlayState->state.input[2].cur.button, BTN_DLEFT)) {
if ((D_8012D10C++ % 5) == 0) {
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
switch (dbCamera->sub.unk_0A) {
@ -1152,8 +1152,8 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DRIGHT)) {
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
switch (dbCamera->sub.unk_0A) {
case 1:
@ -1201,8 +1201,8 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].cur.button, BTN_DRIGHT)) {
if ((D_8012D10C++ % 5) == 0) {
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ATTENTION_ON, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
switch (dbCamera->sub.unk_0A) {
@ -1353,7 +1353,7 @@ void DbCamera_Update(DbCamera* dbCamera, Camera* cam) {
dbCamera->fov = 60.0f;
dbCamera->rollDegrees = dbCamera->roll * 1.40625f;
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_CLEFT)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
dbCamera->unk_78 = (dbCamera->unk_78 + 1) % 3;
dbCamera->unk_38 = -1;
}
@ -1634,7 +1634,7 @@ void DbCamera_DrawSlotLetters(char* str, s16 y, s16 x, s32 colorId) {
void DbCamera_PrintAllCuts(Camera* cam) {
s32 i;
Audio_PlaySoundGeneral(NA_SE_SY_GET_RUPY, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GET_RUPY, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
osSyncPrintf("@@@\n@@@\n@@@/* ****** spline point data ** start here ***** */\n@@@\n");
for (i = 0; i < ARRAY_COUNT(sDbCameraCuts) - 1; i++) {
@ -1777,8 +1777,8 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
if ((1 << sCurFileIdx) & sMempakFiles) {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DLEFT) ||
CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DRIGHT)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
dbCamera->sub.demoCtrlToggleSwitch ^= 1;
}
cameraStrings[41][9] = sCurFileIdx + 'A';
@ -1791,12 +1791,12 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_A)) {
if (dbCamera->sub.demoCtrlToggleSwitch == 0) {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
dbCamera->sub.demoCtrlMenu++;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
dbCamera->sub.demoCtrlMenu = 0;
}
}
@ -1812,7 +1812,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
}
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_B)) {
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
dbCamera->sub.demoCtrlMenu = 0;
return 1;
}
@ -1848,7 +1848,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_A) ||
CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_B)) {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
if (dbCamera->sub.demoCtrlMenu == DEMO_CTRL_MENU(ACTION_LOAD, MENU_SUCCESS)) {
dbCamera->sub.demoCtrlActionIdx = ACTION_E;
}
@ -1870,7 +1870,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_A) ||
CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_B)) {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
dbCamera->sub.demoCtrlMenu -= 9;
}
block_2:
@ -1904,8 +1904,8 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
sp74[i * 2 + 1] = '\0';
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DRIGHT)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
if (sCurFileIdx >= 4) {
sCurFileIdx = 0;
} else {
@ -1921,8 +1921,8 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
}
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DLEFT)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
if (sCurFileIdx <= 0) {
sCurFileIdx = 4;
} else {
@ -1964,25 +1964,25 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
func_8006376C(0x14, 0x1A, 5, cameraStrings[36]);
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DUP)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
dbCamera->sub.demoCtrlActionIdx = (dbCamera->sub.demoCtrlActionIdx - 1) % 4u;
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DDOWN)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
dbCamera->sub.demoCtrlActionIdx = (dbCamera->sub.demoCtrlActionIdx + 1) % 4u;
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_A)) {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
dbCamera->sub.demoCtrlToggleSwitch = 0;
dbCamera->sub.demoCtrlMenu = DEMO_CTRL_MENU(dbCamera->sub.demoCtrlActionIdx, MENU_INFO);
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_B)) {
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
dbCamera->sub.demoCtrlActionIdx = ACTION_E;
return 1;
}
@ -1994,8 +1994,8 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DUP) ||
CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DDOWN)) {
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
dbCamera->sub.demoCtrlActionIdx = ACTION_E;
}
return 2;
@ -2007,13 +2007,13 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
default: {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DUP)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
dbCamera->sub.demoCtrlMenu = DEMO_CTRL_MENU(ACTION_E, MENU_INFO);
dbCamera->sub.demoCtrlActionIdx = (dbCamera->sub.demoCtrlActionIdx - 1) % 4u;
sCurFileIdx = 0;
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DDOWN)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
dbCamera->sub.demoCtrlMenu = DEMO_CTRL_MENU(ACTION_E, MENU_INFO);
dbCamera->sub.demoCtrlActionIdx = (dbCamera->sub.demoCtrlActionIdx + 1) % 4u;
sCurFileIdx = 0;
@ -2052,7 +2052,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
if (func_800B91B0(cam, dbCamera) == 0) {
Interface_ChangeAlpha(2);
ShrinkWindow_SetVal(0);
Audio_PlaySoundGeneral(NA_SE_SY_GET_RUPY, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GET_RUPY, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
OLib_Vec3fDiffToVecSphGeo(&sp5C, &dbCamera->eye, &dbCamera->at);
DbCamera_CalcUpFromPitchYawRoll(&dbCamera->unk_1C, sp5C.pitch, sp5C.yaw,
@ -2070,7 +2070,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
sDbCamAnim.unk_0A = 1;
sDbCamAnim.unk_0C = 0;
D_8016110C = 0;
Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_L)) {
@ -2085,15 +2085,15 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
if (sLastFileIdx != -1) {
switch (sp74[sCurFileIdx]) {
case '?':
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
sDbCameraCuts[idx1] = sDbCameraCuts[idx2];
sp74[sCurFileIdx] = '?'; // useless
DbCamera_ResetCut(idx2, false);
break;
case '-':
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
sp64 = sDbCameraCuts[idx2];
if (sLastFileIdx < sCurFileIdx) {
@ -2115,8 +2115,8 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
}
break;
default:
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
break;
}
}
@ -2125,7 +2125,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_A)) {
if (sp74[sCurFileIdx] == '?') {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
sp74[sCurFileIdx] = DbCamera_InitCut(idx1, &dbCamera->sub);
if (sp74[sCurFileIdx] == '?') {
func_8006376C(0xF, 0x18, 7, cameraStrings[26]);
@ -2135,7 +2135,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_B)) {
if (sp74[sCurFileIdx] != '?' && sp74[sCurFileIdx] != '-') {
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
sp74[sCurFileIdx] = '?';
DbCamera_ResetCut(idx1, true);
}
@ -2143,7 +2143,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_R)) {
if (sp74[sCurFileIdx] != '?' && sp74[sCurFileIdx] != '-') {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
for (i = 0; i < sDbCameraCuts[idx1].nPoints; i++) {
dbCamera->sub.lookAt[i] = sDbCameraCuts[idx1].lookAt[i];
@ -2165,7 +2165,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DRIGHT)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
if (sCurFileIdx == 0x1E) {
sCurFileIdx = 0;
} else {
@ -2173,7 +2173,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
}
}
if (CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_DLEFT)) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
sCurFileIdx = (sCurFileIdx == 0) ? 0x1E : sCurFileIdx - 1;
}
@ -2187,7 +2187,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
DbCamera_PrintAllCuts(cam);
} else if (CHECK_BTN_ALL(sPlayState->state.input[2].cur.button, BTN_L) &&
CHECK_BTN_ALL(sPlayState->state.input[2].press.button, BTN_CLEFT)) {
Audio_PlaySoundGeneral(NA_SE_SY_GET_RUPY, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GET_RUPY, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
for (i = 0; i < ARRAY_COUNT(sDbCameraCuts) - 1; i++) {
if (sDbCameraCuts[i].nPoints != 0) {
osSyncPrintf("\n@@@ /* CUT [%d]\t*/", i);
@ -2203,7 +2203,7 @@ s32 DbCamera_UpdateDemoControl(DbCamera* dbCamera, Camera* cam) {
Interface_ChangeAlpha(50);
ShrinkWindow_SetVal(0x20);
D_8016110C = 0;
Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
func_8006376C(4, 7, 5, cameraStrings[28]);

View File

@ -6,9 +6,9 @@
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
SpeedMeter D_801664D0;
struct_801664F0 D_801664F0;
struct_80166500 D_80166500;
VisMono sMonoColors;
VisCvg sVisCvg;
VisZBuf sVisZBuf;
VisMono sVisMono;
ViMode sViMode;
FaultClient sGameFaultClient;
u16 sLastButtonPressed;
@ -31,41 +31,43 @@ void GameState_FaultPrint(void) {
}
}
void GameState_SetFBFilter(Gfx** gfx) {
Gfx* gfxP;
gfxP = *gfx;
void GameState_SetFBFilter(Gfx** gfxP) {
Gfx* gfx = *gfxP;
if ((R_FB_FILTER_TYPE > 0) && (R_FB_FILTER_TYPE < 5)) {
D_801664F0.type = R_FB_FILTER_TYPE;
D_801664F0.color.r = R_FB_FILTER_PRIM_COLOR(0);
D_801664F0.color.g = R_FB_FILTER_PRIM_COLOR(1);
D_801664F0.color.b = R_FB_FILTER_PRIM_COLOR(2);
D_801664F0.color.a = R_FB_FILTER_A;
func_800ACE98(&D_801664F0, &gfxP);
} else if ((R_FB_FILTER_TYPE == 5) || (R_FB_FILTER_TYPE == 6)) {
D_80166500.useRgba = (R_FB_FILTER_TYPE == 6);
D_80166500.primColor.r = R_FB_FILTER_PRIM_COLOR(0);
D_80166500.primColor.g = R_FB_FILTER_PRIM_COLOR(1);
D_80166500.primColor.b = R_FB_FILTER_PRIM_COLOR(2);
D_80166500.primColor.a = R_FB_FILTER_A;
D_80166500.envColor.r = R_FB_FILTER_ENV_COLOR(0);
D_80166500.envColor.g = R_FB_FILTER_ENV_COLOR(1);
D_80166500.envColor.b = R_FB_FILTER_ENV_COLOR(2);
D_80166500.envColor.a = R_FB_FILTER_A;
func_800AD958(&D_80166500, &gfxP);
} else if (R_FB_FILTER_TYPE == 7) {
sMonoColors.unk_00 = 0;
sMonoColors.primColor.r = R_FB_FILTER_PRIM_COLOR(0);
sMonoColors.primColor.g = R_FB_FILTER_PRIM_COLOR(1);
sMonoColors.primColor.b = R_FB_FILTER_PRIM_COLOR(2);
sMonoColors.primColor.a = R_FB_FILTER_A;
sMonoColors.envColor.r = R_FB_FILTER_ENV_COLOR(0);
sMonoColors.envColor.g = R_FB_FILTER_ENV_COLOR(1);
sMonoColors.envColor.b = R_FB_FILTER_ENV_COLOR(2);
sMonoColors.envColor.a = R_FB_FILTER_A;
VisMono_Draw(&sMonoColors, &gfxP);
if ((R_FB_FILTER_TYPE >= FB_FILTER_CVG_RGB) && (R_FB_FILTER_TYPE <= FB_FILTER_CVG_RGB_FOG)) {
// Visualize coverage
sVisCvg.vis.type = FB_FILTER_TO_CVG_TYPE(R_FB_FILTER_TYPE);
sVisCvg.vis.primColor.r = R_FB_FILTER_PRIM_COLOR(0);
sVisCvg.vis.primColor.g = R_FB_FILTER_PRIM_COLOR(1);
sVisCvg.vis.primColor.b = R_FB_FILTER_PRIM_COLOR(2);
sVisCvg.vis.primColor.a = R_FB_FILTER_A;
VisCvg_Draw(&sVisCvg, &gfx);
} else if ((R_FB_FILTER_TYPE == FB_FILTER_ZBUF_IA) || (R_FB_FILTER_TYPE == FB_FILTER_ZBUF_RGBA)) {
// Visualize z-buffer
sVisZBuf.vis.type = (R_FB_FILTER_TYPE == FB_FILTER_ZBUF_RGBA);
sVisZBuf.vis.primColor.r = R_FB_FILTER_PRIM_COLOR(0);
sVisZBuf.vis.primColor.g = R_FB_FILTER_PRIM_COLOR(1);
sVisZBuf.vis.primColor.b = R_FB_FILTER_PRIM_COLOR(2);
sVisZBuf.vis.primColor.a = R_FB_FILTER_A;
sVisZBuf.vis.envColor.r = R_FB_FILTER_ENV_COLOR(0);
sVisZBuf.vis.envColor.g = R_FB_FILTER_ENV_COLOR(1);
sVisZBuf.vis.envColor.b = R_FB_FILTER_ENV_COLOR(2);
sVisZBuf.vis.envColor.a = R_FB_FILTER_A;
VisZBuf_Draw(&sVisZBuf, &gfx);
} else if (R_FB_FILTER_TYPE == FB_FILTER_MONO) {
// Monochrome filter
sVisMono.vis.type = 0;
sVisMono.vis.primColor.r = R_FB_FILTER_PRIM_COLOR(0);
sVisMono.vis.primColor.g = R_FB_FILTER_PRIM_COLOR(1);
sVisMono.vis.primColor.b = R_FB_FILTER_PRIM_COLOR(2);
sVisMono.vis.primColor.a = R_FB_FILTER_A;
sVisMono.vis.envColor.r = R_FB_FILTER_ENV_COLOR(0);
sVisMono.vis.envColor.g = R_FB_FILTER_ENV_COLOR(1);
sVisMono.vis.envColor.b = R_FB_FILTER_ENV_COLOR(2);
sVisMono.vis.envColor.a = R_FB_FILTER_A;
VisMono_Draw(&sVisMono, &gfx);
}
*gfx = gfxP;
*gfxP = gfx;
}
void func_800C4344(GameState* gameState) {
@ -420,9 +422,9 @@ void GameState_Init(GameState* gameState, GameStateFunc init, GraphicsContext* g
startTime = endTime;
LOG_CHECK_NULL_POINTER("this->cleanup", gameState->destroy);
func_800ACE70(&D_801664F0);
func_800AD920(&D_80166500);
VisMono_Init(&sMonoColors);
VisCvg_Init(&sVisCvg);
VisZBuf_Init(&sVisZBuf);
VisMono_Init(&sVisMono);
if (SREG(48) == 0) {
ViMode_Init(&sViMode);
}
@ -450,9 +452,9 @@ void GameState_Destroy(GameState* gameState) {
}
func_800AA0F0();
SpeedMeter_Destroy(&D_801664D0);
func_800ACE90(&D_801664F0);
func_800AD950(&D_80166500);
VisMono_Destroy(&sMonoColors);
VisCvg_Destroy(&sVisCvg);
VisZBuf_Destroy(&sVisZBuf);
VisMono_Destroy(&sVisMono);
if (SREG(48) == 0) {
ViMode_Destroy(&sViMode);
}

View File

@ -300,7 +300,6 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) {
GameState_ReqPadData(gameState);
GameState_Update(gameState);
DrawColViewer();
OPEN_DISPS(gfxCtx);

View File

@ -624,7 +624,7 @@ void func_8002C7BC(TargetContext* targetCtx, Player* player, Actor* actorArg, Pl
lockOnSfxId = CHECK_FLAG_ALL(actorArg->flags, ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE) ? NA_SE_SY_LOCK_ON
: NA_SE_SY_LOCK_ON_HUMAN;
func_80078884(lockOnSfxId);
Sfx_PlaySfxCentered(lockOnSfxId);
}
targetCtx->targetCenterPos.x = actorArg->world.pos.x;
@ -2202,7 +2202,7 @@ void func_8002F7A0(PlayState* play, Actor* actor, f32 arg2, s16 arg3, f32 arg4)
void Player_PlaySfx(Actor* actor, u16 sfxId) {
if (actor->id != ACTOR_PLAYER || sfxId < NA_SE_VO_LI_SWORD_N || sfxId > NA_SE_VO_LI_ELECTRIC_SHOCK_LV_KID) {
Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &D_801333E0 , &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale , &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
freqMultiplier = CVarGetFloat(CVAR_AUDIO("LinkVoiceFreqMultiplier"), 1.0);
if (freqMultiplier <= 0) {
@ -2210,12 +2210,12 @@ void Player_PlaySfx(Actor* actor, u16 sfxId) {
}
// Authentic behavior uses D_801333E0 for both freqScale and a4
// Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &D_801333E0 , &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &freqMultiplier, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &freqMultiplier, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
void Audio_PlayActorSound2(Actor* actor, u16 sfxId) {
func_80078914(&actor->projectedPos, sfxId);
Sfx_PlaySfxAtPos(&actor->projectedPos, sfxId);
}
void func_8002F850(PlayState* play, Actor* actor) {
@ -2231,8 +2231,8 @@ void func_8002F850(PlayState* play, Actor* actor) {
sfxId = SurfaceType_GetSfx(&play->colCtx, actor->floorPoly, actor->floorBgId);
}
func_80078914(&actor->projectedPos, NA_SE_EV_BOMB_BOUND);
func_80078914(&actor->projectedPos, sfxId + SFX_FLAG);
Sfx_PlaySfxAtPos(&actor->projectedPos, NA_SE_EV_BOMB_BOUND);
Sfx_PlaySfxAtPos(&actor->projectedPos, sfxId + SFX_FLAG);
}
void func_8002F8F0(Actor* actor, u16 sfxId) {
@ -2654,7 +2654,7 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
actor = NULL;
if (actorCtx->targetCtx.unk_4B != 0) {
actorCtx->targetCtx.unk_4B = 0;
func_80078884(NA_SE_SY_LOCK_OFF);
Sfx_PlaySfxCentered(NA_SE_SY_LOCK_OFF);
}
}
@ -2755,15 +2755,15 @@ void Actor_Draw(PlayState* play, Actor* actor) {
void func_80030ED8(Actor* actor) {
if (actor->flags & ACTOR_FLAG_SFX_AT_POS) {
Audio_PlaySoundGeneral(actor->sfx, &actor->projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(actor->sfx, &actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else if (actor->flags & ACTOR_FLAG_SFX_AT_CENTER) {
func_80078884(actor->sfx);
Sfx_PlaySfxCentered(actor->sfx);
} else if (actor->flags & ACTOR_FLAG_SFX_AT_CENTER2) {
func_800788CC(actor->sfx);
Sfx_PlaySfxCentered2(actor->sfx);
} else if (actor->flags & ACTOR_FLAG_SFX_AS_TIMER) {
func_800F4C58(&D_801333D4, NA_SE_SY_TIMER - SFX_FLAG, (s8)(actor->sfx - 1));
func_800F4C58(&gSfxDefaultPos, NA_SE_SY_TIMER - SFX_FLAG, (s8)(actor->sfx - 1));
} else {
func_80078914(&actor->projectedPos, actor->sfx);
Sfx_PlaySfxAtPos(&actor->projectedPos, actor->sfx);
}
}
@ -5737,8 +5737,8 @@ void func_80036E50(u16 textId, s16 arg1) {
Flags_SetInfTable(INFTABLE_0C);
return;
case 0x1033:
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
Flags_SetInfTable(INFTABLE_0E);
return;
@ -6201,7 +6201,7 @@ s32 func_80037CB8(PlayState* play, Actor* actor, s16 arg2) {
case TEXT_STATE_CHOICE:
case TEXT_STATE_EVENT:
if (Message_ShouldAdvance(play) && func_80037C94(play, actor, arg2)) {
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CANCEL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
msgCtx->msgMode = MSGMODE_TEXT_CLOSING;
ret = true;
}

View File

@ -6168,7 +6168,7 @@ s32 Camera_Demo5(Camera* camera) {
pad = sDemo5PrevSfxFrame - camera->play->state.frames;
if ((pad >= 0x33) || (pad < -0x32)) {
func_80078884(camera->data1);
Sfx_PlaySfxCentered(camera->data1);
}
sDemo5PrevSfxFrame = camera->play->state.frames;
@ -7362,11 +7362,11 @@ s32 Camera_DbgChangeMode(Camera* camera) {
if (!gDbgCamEnabled && camera->play->activeCamera == MAIN_CAM) {
if (CHECK_BTN_ALL(D_8015BD7C->state.input[2].press.button, BTN_CUP)) {
osSyncPrintf("attention sound URGENCY\n");
func_80078884(NA_SE_SY_ATTENTION_URGENCY);
Sfx_PlaySfxCentered(NA_SE_SY_ATTENTION_URGENCY);
}
if (CHECK_BTN_ALL(D_8015BD7C->state.input[2].press.button, BTN_CDOWN)) {
osSyncPrintf("attention sound NORMAL\n");
func_80078884(NA_SE_SY_ATTENTION_ON);
Sfx_PlaySfxCentered(NA_SE_SY_ATTENTION_ON);
}
if (CHECK_BTN_ALL(D_8015BD7C->state.input[2].press.button, BTN_CRIGHT)) {
@ -7783,7 +7783,7 @@ s32 Camera_ChangeModeFlags(Camera* camera, s16 mode, u8 flags) {
if (!((sCameraSettings[camera->setting].unk_00 & 0x3FFFFFFF) & (1 << mode))) {
if (mode == CAM_MODE_FIRSTPERSON) {
osSyncPrintf("camera: error sound\n");
func_80078884(NA_SE_SY_ERROR);
Sfx_PlaySfxCentered(NA_SE_SY_ERROR);
}
if (camera->mode != CAM_MODE_NORMAL) {
@ -7871,20 +7871,20 @@ s32 Camera_ChangeModeFlags(Camera* camera, s16 mode, u8 flags) {
if (camera->status == CAM_STAT_ACTIVE) {
switch (modeChangeFlags) {
case 1:
func_80078884(0);
Sfx_PlaySfxCentered(0);
break;
case 2:
if (camera->play->roomCtx.curRoom.behaviorType1 == ROOM_BEHAVIOR_TYPE1_1) {
func_80078884(NA_SE_SY_ATTENTION_URGENCY);
Sfx_PlaySfxCentered(NA_SE_SY_ATTENTION_URGENCY);
} else {
func_80078884(NA_SE_SY_ATTENTION_ON);
Sfx_PlaySfxCentered(NA_SE_SY_ATTENTION_ON);
}
break;
case 4:
func_80078884(NA_SE_SY_ATTENTION_URGENCY);
Sfx_PlaySfxCentered(NA_SE_SY_ATTENTION_URGENCY);
break;
case 8:
func_80078884(NA_SE_SY_ATTENTION_ON);
Sfx_PlaySfxCentered(NA_SE_SY_ATTENTION_ON);
break;
}
}

View File

@ -1607,10 +1607,10 @@ void CollisionCheck_HitSolid(PlayState* play, ColliderInfo* info, Collider* coll
if (flags == TOUCH_SFX_NORMAL && collider->colType != COLTYPE_METAL) {
EffectSsHitMark_SpawnFixedScale(play, EFFECT_HITMARK_WHITE, hitPos);
if (collider->actor == NULL) {
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &collider->actor->projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &collider->actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
} else if (flags == TOUCH_SFX_NORMAL) { // collider->colType == COLTYPE_METAL
EffectSsHitMark_SpawnFixedScale(play, EFFECT_HITMARK_METAL, hitPos);
@ -1622,18 +1622,18 @@ void CollisionCheck_HitSolid(PlayState* play, ColliderInfo* info, Collider* coll
} else if (flags == TOUCH_SFX_HARD) {
EffectSsHitMark_SpawnFixedScale(play, EFFECT_HITMARK_WHITE, hitPos);
if (collider->actor == NULL) {
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &collider->actor->projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &collider->actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
} else if (flags == TOUCH_SFX_WOOD) {
EffectSsHitMark_SpawnFixedScale(play, EFFECT_HITMARK_DUST, hitPos);
if (collider->actor == NULL) {
Audio_PlaySoundGeneral(NA_SE_IT_REFLECTION_WOOD, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_REFLECTION_WOOD, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
Audio_PlaySoundGeneral(NA_SE_IT_REFLECTION_WOOD, &collider->actor->projectedPos, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_REFLECTION_WOOD, &collider->actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
}
@ -1644,17 +1644,17 @@ void CollisionCheck_HitSolid(PlayState* play, ColliderInfo* info, Collider* coll
s32 CollisionCheck_SwordHitAudio(Collider* at, ColliderInfo* acInfo) {
if (at->actor != NULL && at->actor->category == ACTORCAT_PLAYER) {
if (acInfo->elemType == ELEMTYPE_UNK0) {
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_STRIKE, &at->actor->projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_STRIKE, &at->actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
} else if (acInfo->elemType == ELEMTYPE_UNK1) {
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_STRIKE_HARD, &at->actor->projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SWORD_STRIKE_HARD, &at->actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
} else if (acInfo->elemType == ELEMTYPE_UNK2) {
Audio_PlaySoundGeneral(NA_SE_PL_WALK_GROUND - SFX_FLAG, &at->actor->projectedPos, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_PL_WALK_GROUND - SFX_FLAG, &at->actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else if (acInfo->elemType == ELEMTYPE_UNK3) {
Audio_PlaySoundGeneral(NA_SE_PL_WALK_GROUND - SFX_FLAG, &at->actor->projectedPos, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_PL_WALK_GROUND - SFX_FLAG, &at->actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
return 1;
@ -1691,7 +1691,7 @@ void CollisionCheck_HitEffects(PlayState* play, Collider* at, ColliderInfo* atIn
} else if (sHitInfo[ac->colType].effect == HIT_WOOD) {
if (at->actor == NULL) {
CollisionCheck_SpawnShieldParticles(play, hitPos);
Audio_PlaySoundGeneral(NA_SE_IT_REFLECTION_WOOD, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_REFLECTION_WOOD, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
CollisionCheck_SpawnShieldParticlesWood(play, hitPos, &at->actor->projectedPos);
}
@ -1704,10 +1704,10 @@ void CollisionCheck_HitEffects(PlayState* play, Collider* at, ColliderInfo* atIn
} else {
EffectSsHitMark_SpawnFixedScale(play, EFFECT_HITMARK_WHITE, hitPos);
if (ac->actor == NULL) {
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &ac->actor->projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_BOUND, &ac->actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
}
}
@ -3460,7 +3460,7 @@ void CollisionCheck_SpawnShieldParticles(PlayState* play, Vec3f* v) {
*/
void CollisionCheck_SpawnShieldParticlesMetal(PlayState* play, Vec3f* v) {
CollisionCheck_SpawnShieldParticles(play, v);
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_REFLECT_SW, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_REFLECT_SW, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
/**
@ -3468,7 +3468,7 @@ void CollisionCheck_SpawnShieldParticlesMetal(PlayState* play, Vec3f* v) {
*/
void CollisionCheck_SpawnShieldParticlesMetalSound(PlayState* play, Vec3f* v, Vec3f* pos) {
CollisionCheck_SpawnShieldParticles(play, v);
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_REFLECT_SW, pos, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_REFLECT_SW, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
/**
@ -3508,7 +3508,7 @@ void CollisionCheck_SpawnShieldParticlesWood(PlayState* play, Vec3f* v, Vec3f* a
initWood.lightPoint.z = initWood.position.z;
Effect_Add(play, &effectIndex, EFFECT_SHIELD_PARTICLE, 0, 1, &initWood);
Audio_PlaySoundGeneral(NA_SE_IT_REFLECTION_WOOD, actorPos, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_REFLECTION_WOOD, actorPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
/**

View File

@ -285,7 +285,7 @@ void func_80064824(PlayState* play, CutsceneContext* csCtx, CsCmdBase* cmd) {
play->roomCtx.unk_74[0] += 0x14;
}
if (csCtx->frames == 0x30F) {
func_80078884(NA_SE_EV_DEKU_DEATH);
Sfx_PlaySfxCentered(NA_SE_EV_DEKU_DEATH);
} else if (csCtx->frames == 0x2CD) {
play->roomCtx.unk_74[0] = 0;
}
@ -299,7 +299,7 @@ void func_80064824(PlayState* play, CutsceneContext* csCtx, CsCmdBase* cmd) {
break;
case 13:
if (play->roomCtx.unk_74[1] == 0) {
func_80078884(NA_SE_EV_TRIFORCE_FLASH);
Sfx_PlaySfxCentered(NA_SE_EV_TRIFORCE_FLASH);
}
if (play->roomCtx.unk_74[1] < 0xFF) {
play->roomCtx.unk_74[1] += 5;
@ -307,7 +307,7 @@ void func_80064824(PlayState* play, CutsceneContext* csCtx, CsCmdBase* cmd) {
break;
case 14:
if (sp3F != 0) {
func_800BC490(play, 1);
Play_SetViewpoint(play, 1);
}
break;
case 15:
@ -350,16 +350,16 @@ void func_80064824(PlayState* play, CutsceneContext* csCtx, CsCmdBase* cmd) {
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER);
break;
case 22:
D_801614B0.r = 255;
D_801614B0.g = 255;
D_801614B0.b = 255;
D_801614B0.a = 255;
gVisMonoColor.r = 255;
gVisMonoColor.g = 255;
gVisMonoColor.b = 255;
gVisMonoColor.a = 255;
break;
case 23:
D_801614B0.r = 255;
D_801614B0.g = 180;
D_801614B0.b = 100;
D_801614B0.a = 255.0f * temp;
gVisMonoColor.r = 255;
gVisMonoColor.g = 180;
gVisMonoColor.b = 100;
gVisMonoColor.a = 255.0f * temp;
break;
case 24:
play->roomCtx.curRoom.segment = NULL;
@ -412,7 +412,7 @@ void func_80064824(PlayState* play, CutsceneContext* csCtx, CsCmdBase* cmd) {
if (sp3F != 0) {
play->envCtx.sandstormState = SANDSTORM_FILL;
}
func_800788CC(NA_SE_EV_SAND_STORM - SFX_FLAG);
Sfx_PlaySfxCentered2(NA_SE_EV_SAND_STORM - SFX_FLAG);
break;
case 33:
gSaveContext.sunsSongState = SUNSSONG_START;
@ -514,7 +514,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
CHECK_BTN_ALL(play->state.input[0].press.button, BTN_B) ||
CHECK_BTN_ALL(play->state.input[0].press.button, BTN_START)) &&
(gSaveContext.fileNum != 0xFEDC) && (play->transitionTrigger == TRANS_TRIGGER_OFF)) {
Audio_PlaySoundGeneral(NA_SE_SY_PIECE_OF_HEART, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_PIECE_OF_HEART, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
temp = 1;
}
@ -1328,15 +1328,15 @@ void Cutscene_Command_TransitionFX(PlayState* play, CutsceneContext* csCtx, CsCm
if (cmd->base == 1) {
play->envCtx.screenFillColor[3] = 255.0f * temp;
if ((temp == 0.0f) && (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0)) {
Audio_PlaySoundGeneral(NA_SE_SY_WHITE_OUT_S, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_WHITE_OUT_S, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
} else if ((temp == 0.0f) &&
((gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_ENTRANCE) || (gSaveContext.entranceIndex == ENTR_CASTLE_GROUNDS_SOUTH_EXIT) ||
(gSaveContext.entranceIndex == ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF))) {
Audio_PlaySoundGeneral(NA_SE_EV_WHITE_OUT, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_WHITE_OUT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
} else if ((temp == 0.0f) && (play->sceneNum == SCENE_INSIDE_GANONS_CASTLE)) {
func_800788CC(NA_SE_EV_WHITE_OUT);
Sfx_PlaySfxCentered2(NA_SE_EV_WHITE_OUT);
}
} else {
play->envCtx.screenFillColor[3] = (1.0f - temp) * 255.0f;
@ -2052,7 +2052,7 @@ void func_80068C3C(PlayState* play, CutsceneContext* csCtx) {
csCtx->frames++;
if (dREG(95) != 0) {
Cutscene_ProcessCommands(play, csCtx, D_8012D1F0);
Cutscene_ProcessCommands(play, csCtx, gDebugCutsceneScript);
} else {
Cutscene_ProcessCommands(play, csCtx, play->csCtx.segment);
}

View File

@ -974,7 +974,7 @@ void EnItem00_Update(Actor* thisx, PlayState* play) {
}
if ((*params <= ITEM00_RUPEE_RED) || (*params == ITEM00_RUPEE_ORANGE)) {
Audio_PlaySoundGeneral(NA_SE_SY_GET_RUPY, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GET_RUPY, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else if (getItemId != GI_NONE) {
if (Actor_HasParent(&this->actor, play)) {
Flags_SetCollectible(play, this->collectibleFlag);
@ -982,7 +982,7 @@ void EnItem00_Update(Actor* thisx, PlayState* play) {
}
return;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_GET_ITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GET_ITEM, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
Flags_SetCollectible(play, this->collectibleFlag);

View File

@ -84,7 +84,7 @@ void TransitionCircle_Start(void* thisx) {
} else {
this->texY = 0x1F4;
if (this->appearanceType == TCA_RIPPLE) {
Audio_PlaySoundGeneral(NA_SE_OC_SECRET_WARP_OUT, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_OC_SECRET_WARP_OUT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
guPerspective(&this->projection, &this->normal, 60.0f, (4.0f / 3.0f), 10.0f, 12800.0f, 1.0f);
@ -109,7 +109,7 @@ void TransitionCircle_Update(void* thisx, s32 updateRate) {
if (this->direction != 0) {
if (this->texY == 0) {
if (this->appearanceType == TCA_RIPPLE) {
Audio_PlaySoundGeneral(NA_SE_OC_SECRET_WARP_IN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_OC_SECRET_WARP_IN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
this->texY += this->speed * 3 / updateRate;

View File

@ -914,10 +914,10 @@ void Environment_Update(PlayState* play, EnvironmentContext* envCtx, LightContex
osSyncPrintf("\nnext_zelda_time=[%x]", ((void)0, gSaveContext.nextDayTime));
if (((void)0, gSaveContext.nextDayTime) == 0xFF0E) {
func_80078884(NA_SE_EV_CHICKEN_CRY_M);
Sfx_PlaySfxCentered(NA_SE_EV_CHICKEN_CRY_M);
gSaveContext.nextDayTime = 0xFFFF;
} else if (((void)0, gSaveContext.nextDayTime) == 0xFF0D) {
func_800788CC(NA_SE_EV_DOG_CRY_EVENING);
Sfx_PlaySfxCentered2(NA_SE_EV_DOG_CRY_EVENING);
gSaveContext.nextDayTime = 0xFFFF;
}
}
@ -2076,7 +2076,7 @@ void func_80075B44(PlayState* play) {
break;
case 2:
if (gSaveContext.dayTime > 0xC000) {
func_800788CC(NA_SE_EV_DOG_CRY_EVENING);
Sfx_PlaySfxCentered2(NA_SE_EV_DOG_CRY_EVENING);
play->envCtx.unk_E0++;
}
break;
@ -2105,7 +2105,7 @@ void func_80075B44(PlayState* play) {
gSaveContext.totalDays++;
gSaveContext.bgsDayCount++;
gSaveContext.dogIsLost = true;
func_80078884(NA_SE_EV_CHICKEN_CRY_M);
Sfx_PlaySfxCentered(NA_SE_EV_CHICKEN_CRY_M);
if ((Inventory_ReplaceItem(play, ITEM_WEIRD_EGG, ITEM_CHICKEN) ||
Inventory_HatchPocketCucco(play)) &&
play->csCtx.state == 0 && !Player_InCsMode(play)) {

View File

@ -572,14 +572,17 @@ void Color_RGBA8_Copy(Color_RGBA8* dst, Color_RGBA8* src) {
dst->a = src->a;
}
void func_80078884(u16 sfxId) {
Audio_PlaySoundGeneral(sfxId, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
void Sfx_PlaySfxCentered(u16 sfxId) {
Audio_PlaySoundGeneral(sfxId, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
void func_800788CC(u16 sfxId) {
Audio_PlaySoundGeneral(sfxId, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
void Sfx_PlaySfxCentered2(u16 sfxId) {
Audio_PlaySoundGeneral(sfxId, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
void func_80078914(Vec3f* arg0, u16 sfxId) {
Audio_PlaySoundGeneral(sfxId, arg0, 4, &D_801333E0, &D_801333E0, &D_801333E8);
void Sfx_PlaySfxAtPos(Vec3f* arg0, u16 sfxId) {
Audio_PlaySoundGeneral(sfxId, arg0, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}

View File

@ -648,7 +648,7 @@ void HealthMeter_HandleCriticalAlarm(PlayState* play) {
interfaceCtx->unk_22C = 0;
if (CVarGetInteger(CVAR_ENHANCEMENT("LowHpAlarm"), 0) == 0 && !Player_InCsMode(play) && (play->pauseCtx.state == 0) &&
(play->pauseCtx.debugState == 0) && HealthMeter_IsCritical() && !Play_InCsMode(play)) {
func_80078884(NA_SE_SY_HITPOINT_ALARM);
Sfx_PlaySfxCentered(NA_SE_SY_HITPOINT_ALARM);
}
}
} else {

View File

@ -810,10 +810,10 @@ void Minimap_Draw(PlayState* play) {
if (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_L) && !Play_InCsMode(play) && enableMapToggle) {
osSyncPrintf("Game_play_demo_mode_check=%d\n", Play_InCsMode(play));
// clang-format off
if (!R_MINIMAP_DISABLED) { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_UP, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8); }
else { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_DOWN, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8); }
if (!R_MINIMAP_DISABLED) { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_UP, &gSfxDefaultPos, 4,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); }
else { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_DOWN, &gSfxDefaultPos, 4,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); }
// clang-format on
R_MINIMAP_DISABLED ^= 1;
}
@ -965,10 +965,10 @@ void Minimap_Draw(PlayState* play) {
if (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_L) && !Play_InCsMode(play) && enableMapToggle) {
// clang-format off
if (!R_MINIMAP_DISABLED) { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_UP, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8); }
else { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_DOWN, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8); }
if (!R_MINIMAP_DISABLED) { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_UP, &gSfxDefaultPos, 4,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); }
else { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_DOWN, &gSfxDefaultPos, 4,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); }
// clang-format on
R_MINIMAP_DISABLED ^= 1;
}

View File

@ -154,7 +154,7 @@ u8 Message_ShouldAdvance(PlayState* play) {
: CHECK_BTN_ALL(input->press.button, BTN_B);
if (CHECK_BTN_ALL(input->press.button, BTN_A) || isB_Held || CHECK_BTN_ALL(input->press.button, BTN_CUP)) {
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_PASS, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_PASS, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
return CHECK_BTN_ALL(input->press.button, BTN_A) || isB_Held || CHECK_BTN_ALL(input->press.button, BTN_CUP);
}
@ -179,7 +179,7 @@ void Message_CloseTextbox(PlayState* play) {
msgCtx->stateTimer = 2;
msgCtx->msgMode = MSGMODE_TEXT_CLOSING;
msgCtx->textboxEndType = TEXTBOX_ENDTYPE_DEFAULT;
Audio_PlaySoundGeneral(0, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
@ -195,7 +195,7 @@ void Message_HandleChoiceSelection(PlayState* play, u8 numChoices) {
if (msgCtx->choiceIndex > 128) {
msgCtx->choiceIndex = 0;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else if ((input->rel.stick_y <= -30 && !sAnalogStickHeld) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) {
sAnalogStickHeld = true;
@ -203,7 +203,7 @@ void Message_HandleChoiceSelection(PlayState* play, u8 numChoices) {
if (msgCtx->choiceIndex > numChoices) {
msgCtx->choiceIndex = numChoices;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else if (ABS(input->rel.stick_y) < 30) {
sAnalogStickHeld = false;
@ -724,7 +724,7 @@ u16 Message_DrawItemIcon(PlayState* play, u16 itemId, Gfx** p, u16 i) {
MessageContext* msgCtx = &play->msgCtx;
// clang-format off
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { Audio_PlaySoundGeneral(0, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); }
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { Audio_PlaySoundGeneral(0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); }
// clang-format on
gDPPipeSync(gfx++);
@ -882,7 +882,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) {
case MESSAGE_BOX_BREAK:
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) {
if (!sTextboxSkipped) {
Audio_PlaySoundGeneral(0, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
msgCtx->msgMode = MSGMODE_TEXT_AWAIT_NEXT;
Font_LoadMessageBoxIcon(font, TEXTBOX_ICON_TRIANGLE);
} else {
@ -899,7 +899,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) {
case MESSAGE_TEXTID:
msgCtx->textboxEndType = TEXTBOX_ENDTYPE_HAS_NEXT;
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) {
Audio_PlaySoundGeneral(0, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
msgCtx->msgMode = MSGMODE_TEXT_DONE;
Font_LoadMessageBoxIcon(font, TEXTBOX_ICON_TRIANGLE);
}
@ -970,8 +970,8 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) {
// "Sound (SE)"
osSyncPrintf("サウンド(SE)\n");
sfxHi = msgCtx->msgBufDecoded[i + 1] << 8;
Audio_PlaySoundGeneral(sfxHi | msgCtx->msgBufDecoded[i + 2], &D_801333D4, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(sfxHi | msgCtx->msgBufDecoded[i + 2], &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
i += 2;
break;
@ -980,7 +980,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) {
break;
case MESSAGE_BACKGROUND:
// clang-format off
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { Audio_PlaySoundGeneral(0, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); }
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) { Audio_PlaySoundGeneral(0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); }
// clang-format on
gDPPipeSync(gfx++);
gDPSetCombineMode(gfx++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
@ -1062,8 +1062,8 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) {
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) {
msgCtx->msgMode = MSGMODE_TEXT_DONE;
if (msgCtx->textboxEndType == TEXTBOX_ENDTYPE_DEFAULT) {
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_END, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_END, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
Font_LoadMessageBoxIcon(font, TEXTBOX_ICON_SQUARE);
if (play->csCtx.state == 0) {
Interface_SetDoAction(play, DO_ACTION_RETURN);
@ -1094,7 +1094,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) {
return;
case MESSAGE_PERSISTENT:
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) {
Audio_PlaySoundGeneral(0, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
msgCtx->msgMode = MSGMODE_TEXT_DONE;
msgCtx->textboxEndType = TEXTBOX_ENDTYPE_PERSISTENT;
}
@ -1105,14 +1105,14 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) {
msgCtx->msgMode = MSGMODE_TEXT_DONE;
msgCtx->textboxEndType = TEXTBOX_ENDTYPE_EVENT;
Font_LoadMessageBoxIcon(font, TEXTBOX_ICON_TRIANGLE);
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_END, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_END, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
*gfxP = gfx;
return;
default:
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING && i + 1 == msgCtx->textDrawPos &&
msgCtx->textDelayTimer == msgCtx->textDelay) {
Audio_PlaySoundGeneral(0, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
Message_DrawTextChar(play, &font->charTexBuf[charTexIdx], &gfx);
charTexIdx += FONT_CHAR_TEX_SIZE;
@ -1812,7 +1812,7 @@ void Message_StartOcarina(PlayState* play, u16 ocarinaActionId) {
osSyncPrintf("ocarina_set 000000000000000000 = %d\n", ocarinaActionId);
msgCtx->ocarinaAction = ocarinaActionId;
if (ocarinaActionId >= OCARINA_ACTION_CHECK_SARIA && ocarinaActionId <= OCARINA_ACTION_CHECK_STORMS) {
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
if (ocarinaActionId == OCARINA_ACTION_SCARECROW_PLAYBACK) {
Message_OpenText(play, 0x86F); // Ocarina
@ -2259,8 +2259,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
if (msgCtx->ocarinaStaff->state < OCARINA_SONG_SARIAS ||
msgCtx->ocarinaStaff->state == OCARINA_SONG_SCARECROW) {
Audio_OcaSetInstrument(0);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
msgCtx->msgMode = MSGMODE_OCARINA_STARTING;
} else {
// "Ocarina_Flog Correct Example Performance"
@ -2269,15 +2269,15 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
msgCtx->msgMode = MSGMODE_SONG_PLAYED;
msgCtx->textBoxType = TEXTBOX_TYPE_OCARINA;
msgCtx->stateTimer = 10;
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Interface_ChangeAlpha(1);
}
} else if (msgCtx->ocarinaAction == OCARINA_ACTION_CHECK_SCARECROW) {
if (msgCtx->ocarinaStaff->state < OCARINA_SONG_SCARECROW) {
Audio_OcaSetInstrument(0);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
msgCtx->stateTimer = 10;
msgCtx->msgMode = MSGMODE_OCARINA_FAIL;
} else {
@ -2287,8 +2287,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
msgCtx->msgMode = MSGMODE_SONG_PLAYED;
msgCtx->textBoxType = TEXTBOX_TYPE_OCARINA;
msgCtx->stateTimer = 10;
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Interface_ChangeAlpha(1);
}
} else if (msgCtx->ocarinaAction == OCARINA_ACTION_FREE_PLAY) {
@ -2298,23 +2298,23 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
msgCtx->msgMode = MSGMODE_SONG_PLAYED;
msgCtx->textBoxType = TEXTBOX_TYPE_OCARINA;
msgCtx->stateTimer = 10;
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
} else {
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
Interface_ChangeAlpha(1);
} else {
Audio_OcaSetInstrument(0);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
msgCtx->msgMode = MSGMODE_OCARINA_STARTING;
}
} else if (msgCtx->ocarinaStaff->state == 0xFF) {
Audio_OcaSetInstrument(0);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
msgCtx->stateTimer = 10;
msgCtx->msgMode = MSGMODE_OCARINA_FAIL;
} else if (isB_Held) {
@ -2641,11 +2641,11 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
osSyncPrintf("z_message.c 取得メロディ=%d\n", ITEM_SONG_MINUET + msgCtx->ocarinaStaff->state);
osSyncPrintf(VT_RST);
msgCtx->stateTimer = 20;
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
} else if (msgCtx->ocarinaStaff->state == 0xFF) {
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
msgCtx->stateTimer = 10;
msgCtx->msgMode = MSGMODE_SONG_PLAYBACK_FAIL;
}
@ -2696,8 +2696,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
msgCtx->ocarinaStaff->state);
gSaveContext.scarecrowLongSongSet = true;
}
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
osSyncPrintf("aaaaaaaaaaaaaa\n");
Audio_OcaSetRecordingState(0);
msgCtx->stateTimer = 10;
@ -2766,8 +2766,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
msgCtx->stateTimer = 20;
gSaveContext.scarecrowSpawnSongSet = true;
msgCtx->msgMode = MSGMODE_SCARECROW_RECORDING_DONE;
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
osSyncPrintf(VT_FGCOL(YELLOW));
osSyncPrintf("\n====================================================================\n");
memcpy(gSaveContext.scarecrowSpawnSong, gScarecrowSpawnSongPtr,
@ -2781,8 +2781,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
// "Played an existing song"
osSyncPrintf("すでに存在する曲吹いた!!! \n");
Audio_OcaSetRecordingState(0);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
Message_CloseTextbox(play);
msgCtx->msgMode = MSGMODE_SCARECROW_RECORDING_FAILED;
}
@ -2807,8 +2807,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
break;
case MSGMODE_MEMORY_GAME_LEFT_SKULLKID_PLAYING:
case MSGMODE_MEMORY_GAME_RIGHT_SKULLKID_PLAYING:
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME_LV - SFX_FLAG, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME_LV - SFX_FLAG, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
msgCtx->ocarinaStaff = Audio_OcaGetDisplayingStaff();
if (msgCtx->ocarinaStaff->pos && sOcarinaNoteBufPos == msgCtx->ocarinaStaff->pos - 1) {
sOcarinaNoteBuf[msgCtx->ocarinaStaff->pos - 1] = msgCtx->ocarinaStaff->noteIdx;
@ -2818,11 +2818,11 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
if (msgCtx->stateTimer == 0) {
if (msgCtx->ocarinaStaff->state == 0) {
if (msgCtx->msgMode == MSGMODE_MEMORY_GAME_LEFT_SKULLKID_PLAYING) {
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
} else {
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME_2, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME_2, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
msgCtx->msgMode++;
}
@ -2840,8 +2840,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
}
break;
case MSGMODE_MEMORY_GAME_PLAYER_PLAYING:
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME_LV - SFX_FLAG, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME_LV - SFX_FLAG, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
msgCtx->ocarinaStaff = Audio_OcaGetPlayingStaff();
if (msgCtx->ocarinaStaff->pos && sOcarinaNoteBufPos == msgCtx->ocarinaStaff->pos - 1) {
sOcarinaNoteBuf[msgCtx->ocarinaStaff->pos - 1] = msgCtx->ocarinaStaff->noteIdx;
@ -2852,14 +2852,14 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
// "Musical round failed"
osSyncPrintf("輪唱失敗!!!!!!!!!\n");
Audio_OcaSetInstrument(0);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_OCARINA_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
msgCtx->stateTimer = 10;
play->msgCtx.ocarinaMode = OCARINA_MODE_03;
} else if (msgCtx->ocarinaStaff->state == 0xD) {
// "Musical round succeeded"
osSyncPrintf("輪唱成功!!!!!!!!!\n");
Audio_PlaySoundGeneral(NA_SE_SY_GET_ITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GET_ITEM, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
msgCtx->msgMode = MSGMODE_MEMORY_GAME_ROUND_SUCCESS;
msgCtx->stateTimer = 30;
}
@ -2875,8 +2875,8 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
msgCtx->stateTimer--;
if (msgCtx->stateTimer == 0) {
if (Audio_OcaMemoryGameGenNote() != 1) {
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
msgCtx->ocarinaStaff = Audio_OcaGetPlayingStaff();
msgCtx->ocarinaStaff->pos = sOcarinaNoteBufPos = 0;
Message_ResetOcarinaNoteState();
@ -3337,11 +3337,11 @@ void Message_Update(PlayState* play) {
} else if (Message_ShouldAdvanceSilent(play)) {
osSyncPrintf("select=%d\n", msgCtx->textboxEndType);
if (msgCtx->textboxEndType == TEXTBOX_ENDTYPE_HAS_NEXT) {
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_PASS, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_PASS, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
Message_ContinueTextbox(play, sNextTextId);
} else {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Message_CloseTextbox(play);
}
}

View File

@ -471,7 +471,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3);
Player_SetCsActionWithHaltedActors(play, &player->actor, 5);
OnePointCutscene_SetCsCamPoints(csCam, D_80120304 | 0x2000, D_80120300, D_8012013C, D_8012021C);
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
OnePointCutscene_Vec3sToVec3f(&mainCam->at, &D_8012013C[D_801202FC - 2].pos);
OnePointCutscene_Vec3sToVec3f(&mainCam->eye, &D_8012021C[D_801202FC - 2].pos);
D_8012013C[D_801202FC - 3].pos.x +=

View File

@ -1607,10 +1607,8 @@ void Inventory_SwapAgeEquipment(void) {
s16 i;
u16 shieldEquipValue;
// Mod Enhancments can utilise the rando flow path
if (IS_RANDO || CVarGetInteger(CVAR_GENERAL("SwitchAge"), 0) || CVarGetInteger(CVAR_GENERAL("SwitchTimeline"), 0)) {
if (IS_RANDO) {
Rando_Inventory_SwapAgeEquipment();
CVarSetInteger(CVAR_GENERAL("SwitchTimeline"), 0);
return;
}
@ -2829,12 +2827,12 @@ void Interface_SetNaviCall(PlayState* play, u16 naviCallState) {
(play->csCtx.state == CS_STATE_IDLE)) {
if (!CVarGetInteger(CVAR_ENHANCEMENT("DisableNaviCallAudio"), 0)) {
// clang-format off
if (naviCallState == 0x1E) { Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8); }
if (naviCallState == 0x1E) { Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &gSfxDefaultPos, 4,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); }
// clang-format on
if (naviCallState == 0x1D) {
func_800F4524(&D_801333D4, NA_SE_VO_NA_HELLO_2, 32);
func_800F4524(&gSfxDefaultPos, NA_SE_VO_NA_HELLO_2, 32);
}
}
@ -2898,8 +2896,8 @@ s32 Health_ChangeBy(PlayState* play, s16 healthChange) {
}
// clang-format off
if (healthChange > 0) { Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8);
if (healthChange > 0) { Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &gSfxDefaultPos, 4,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else if ((gSaveContext.isDoubleDefenseAcquired != 0) && (healthChange < 0)) {
healthChange >>= 1;
osSyncPrintf("ハート減少半分!!=%d\n", healthChange); // "Heart decrease halved!!%d"
@ -3079,7 +3077,7 @@ s32 Magic_RequestChange(PlayState* play, s16 amount, s16 type) {
if ((type != 5) && (gSaveContext.magic - amount) < 0) {
if (gSaveContext.magicCapacity != 0) {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
return false;
}
@ -3095,7 +3093,7 @@ s32 Magic_RequestChange(PlayState* play, s16 amount, s16 type) {
gSaveContext.magicState = MAGIC_STATE_CONSUME_SETUP;
return 1;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
return false;
}
case MAGIC_CONSUME_WAIT_NO_PREVIEW:
@ -3107,7 +3105,7 @@ s32 Magic_RequestChange(PlayState* play, s16 amount, s16 type) {
gSaveContext.magicState = MAGIC_STATE_METER_FLASH_3;
return true;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
return false;
}
case MAGIC_CONSUME_LENS:
@ -3135,7 +3133,7 @@ s32 Magic_RequestChange(PlayState* play, s16 amount, s16 type) {
gSaveContext.magicState = MAGIC_STATE_METER_FLASH_2;
return true;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
return false;
}
case MAGIC_ADD:
@ -3219,8 +3217,8 @@ void Interface_UpdateMagicBar(PlayState* play) {
gSaveContext.magic += 4;
if (gSaveContext.gameMode == 0 && gSaveContext.sceneSetupIndex < 4) {
Audio_PlaySoundGeneral(NA_SE_SY_GAUGE_UP - SFX_FLAG, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GAUGE_UP - SFX_FLAG, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
// "Storage MAGIC_NOW=%d (%d)"
@ -3321,8 +3319,8 @@ void Interface_UpdateMagicBar(PlayState* play) {
!hasLens ||
!play->actorCtx.lensActive) {
play->actorCtx.lensActive = false;
Audio_PlaySoundGeneral(NA_SE_SY_GLASSMODE_OFF, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GLASSMODE_OFF, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
gSaveContext.magicState = MAGIC_STATE_IDLE;
if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) {
sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori);
@ -3377,7 +3375,7 @@ void Interface_UpdateMagicBar(PlayState* play) {
case MAGIC_STATE_ADD:
gSaveContext.magic += 4;
Audio_PlaySoundGeneral(NA_SE_SY_GAUGE_UP - SFX_FLAG, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_GAUGE_UP - SFX_FLAG, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
if (gSaveContext.magic >= gSaveContext.magicTarget) {
gSaveContext.magic = gSaveContext.magicTarget;
gSaveContext.magicState = gSaveContext.prevMagicState;
@ -5798,17 +5796,17 @@ void Interface_Draw(PlayState* play) {
D_80125A5C = 0;
} else if (gSaveContext.timer1Value > 60) {
if (timerDigits[4] == 1) {
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_WOMAN, &D_801333D4, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_WOMAN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else if (gSaveContext.timer1Value >= 11) {
if (timerDigits[4] & 1) {
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_N, &D_801333D4, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_N, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else {
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_E, &D_801333D4, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_E, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
}
@ -5855,8 +5853,8 @@ void Interface_Draw(PlayState* play) {
D_8015FFE2 = 40;
gSaveContext.timer1State = 15;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_N, &D_801333D4, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_N, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
}
@ -5973,17 +5971,17 @@ void Interface_Draw(PlayState* play) {
}
} else if (gSaveContext.timer2Value > 60) {
if (timerDigits[4] == 1) {
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_WOMAN, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_MESSAGE_WOMAN, &gSfxDefaultPos, 4,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else if (gSaveContext.timer2Value > 10) {
if ((timerDigits[4] & 1)) {
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_N, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_N, &gSfxDefaultPos, 4,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else {
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_E, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_E, &gSfxDefaultPos, 4,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else {
gSaveContext.timer2Value++;
@ -5997,8 +5995,8 @@ void Interface_Draw(PlayState* play) {
}
if ((gSaveContext.timer2Value % 60) == 0) {
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_N, &D_801333D4, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_WARNING_COUNT_N, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
}
@ -6363,7 +6361,7 @@ void Interface_Update(PlayState* play) {
gSaveContext.health += 4;
if ((gSaveContext.health & 0xF) < 4) {
Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_HP_RECOVER, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
osSyncPrintf("now_life=%d max_life=%d\n", gSaveContext.health, gSaveContext.healthCapacity);
@ -6400,7 +6398,7 @@ void Interface_Update(PlayState* play) {
if (gSaveContext.rupees < CUR_CAPACITY(UPG_WALLET)) {
gSaveContext.rupeeAccumulator--;
gSaveContext.rupees++;
Audio_PlaySoundGeneral(NA_SE_SY_RUPY_COUNT, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_RUPY_COUNT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
// "Rupee Amount MAX = %d"
osSyncPrintf("ルピー数MAX = %d\n", CUR_CAPACITY(UPG_WALLET));
@ -6416,11 +6414,11 @@ void Interface_Update(PlayState* play) {
gSaveContext.rupees = 0;
}
Audio_PlaySoundGeneral(NA_SE_SY_RUPY_COUNT, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_RUPY_COUNT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
gSaveContext.rupeeAccumulator++;
gSaveContext.rupees--;
Audio_PlaySoundGeneral(NA_SE_SY_RUPY_COUNT, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_RUPY_COUNT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else {
gSaveContext.rupeeAccumulator = 0;

File diff suppressed because it is too large Load Diff

View File

@ -58,5 +58,5 @@ void SoundSource_PlaySfxAtFixedWorldPos(PlayState* play, Vec3f* worldPos, s32 du
source->countdown = duration;
SkinMatrix_Vec3fMtxFMultXYZ(&play->viewProjectionMtxF, &source->worldPos, &source->projectedPos);
Audio_PlaySoundGeneral(sfxId, &source->projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(sfxId, &source->projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}

145
soh/src/code/z_viscvg.c Normal file
View File

@ -0,0 +1,145 @@
/**
* @file z_viscvg.c
*
* This file implements full-screen frame buffer effects involving the visualization of Coverage in various ways.
*
* Coverage is roughly how much of a pixel is covered by a primitive; the final coverage for a frame is stored in the
* color image alpha component where it is used for antialiasing, see PreRender.c and §15 of the programming manual for
* details.
*
* To understand this file, it is helpful to remember that A_MEM is essentially synonymous with coverage, and that
* `GBL_c1/2(p, a, m, b)` usually represents the RDP blender calculation `(p * a + m * b)`.
* Note the division step that is often included in the blender calculation is omitted; the division is skipped if
* force blending (FORCE_BL) is set, which is the case for all render modes used in this file.
*
* Coverage is full when not on an edge, while on an edge it is usually lower. Since coverage is treated as an alpha
* value, edges of primitives where coverage is lower will show up darker than primitive interiors in all of the
* available modes.
*
* Coverage is abbreviated to "cvg"; "FB RGB" ("framebuffer red/green/blue") is the color the pixel originally had
* before the filter is applied.
*/
#include "global.h"
/**
* Draws only coverage: does not retain any of the original pixel RGB, primColor is used as background color.
*/
Gfx sCoverageOnlyDL[] = {
gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | G_RM_VISCVG | G_RM_VISCVG2),
// (blendColor RGB) * (cvg)
gsDPFillRectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1),
gsDPPipeSync(),
gsDPSetBlendColor(0, 0, 0, 8),
gsSPEndDisplayList(),
};
/**
* Draws fog + coverage * RGB of pixels
*
* @bug This easily overflows the blender because the fog value is added to the coverage value.
*/
Gfx sCoverageRGBFogDL[] = {
gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL |
GBL_c1(G_BL_CLR_FOG, G_BL_A_FOG, G_BL_CLR_MEM, G_BL_A_MEM) |
GBL_c2(G_BL_CLR_FOG, G_BL_A_FOG, G_BL_CLR_MEM, G_BL_A_MEM)),
// (fog RGB) * (fog alpha) + (FB RGB) * (cvg)
gsDPFillRectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1),
gsSPEndDisplayList(),
};
/**
* Draws coverage and RGB of pixels
*/
Gfx sCoverageRGBDL[] = {
gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL |
GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_MEM, G_BL_A_MEM) |
GBL_c2(G_BL_CLR_IN, G_BL_0, G_BL_CLR_MEM, G_BL_A_MEM)),
// (FB RGB) * (cvg)
gsDPFillRectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1),
gsSPEndDisplayList(),
};
/**
* Two stage filtering:
*
* 1. Apply a uniform color filter by transparently blending primColor with original frame. The "cloud surface"
* RenderMode is used to preserve the coverage for the second stage.
* 2. Second half is the same as `sCoverageRGBDL`'s, i.e. (RGB from stage 1) * cvg
*/
Gfx sCoverageRGBUniformDL[] = {
gsDPSetCombineMode(G_CC_PRIMITIVE, G_CC_PRIMITIVE),
gsDPSetOtherMode(G_AD_NOTPATTERN | G_CD_DISABLE | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | G_RM_CLD_SURF | G_RM_CLD_SURF2),
// stage 1 color = (primColor RGB) * (primColor Alpha) + (FB RGB) * (1 - primColor Alpha)
gsDPFillRectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1),
gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL |
GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_MEM, G_BL_A_MEM) |
GBL_c2(G_BL_CLR_IN, G_BL_0, G_BL_CLR_MEM, G_BL_A_MEM)),
// final color = (stage 1 RGB) * (cvg)
gsDPFillRectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1),
gsSPEndDisplayList(),
};
void VisCvg_Init(VisCvg* this) {
this->vis.type = FB_FILTER_NONE;
this->vis.scissorType = VIS_NO_SETSCISSOR;
this->vis.primColor.r = 255;
this->vis.primColor.g = 255;
this->vis.primColor.b = 255;
this->vis.primColor.a = 255;
}
void VisCvg_Destroy(VisCvg* this) {
}
void VisCvg_Draw(VisCvg* this, Gfx** gfxP) {
Gfx* gfx = *gfxP;
gDPPipeSync(gfx++);
gDPSetPrimDepth(gfx++, 0xFFFF, 0xFFFF);
if (this->vis.scissorType == VIS_SETSCISSOR) {
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
switch (this->vis.type) {
case FB_FILTER_CVG_RGB:
gSPDisplayList(gfx++, sCoverageRGBDL);
break;
case FB_FILTER_CVG_RGB_UNIFORM:
// Set primitive color for uniform color filter in custom RenderMode
gDPSetColor(gfx++, G_SETPRIMCOLOR, this->vis.primColor.rgba);
gSPDisplayList(gfx++, sCoverageRGBUniformDL);
break;
case FB_FILTER_CVG_ONLY:
// Set background color for G_RM_VISCVG
gDPSetColor(gfx++, G_SETBLENDCOLOR, this->vis.primColor.rgba);
gSPDisplayList(gfx++, sCoverageOnlyDL);
break;
case FB_FILTER_CVG_RGB_FOG:
// Set fog color for custom RenderMode, needs to be close to 0 to not overflow
gDPSetColor(gfx++, G_SETFOGCOLOR, this->vis.primColor.rgba);
gSPDisplayList(gfx++, sCoverageRGBFogDL);
break;
default:
break;
}
gDPPipeSync(gfx++);
*gfxP = gfx;
}

View File

@ -1,137 +1,218 @@
/**
* @file z_vismono.c
*
* This file implements a full-screen framebuffer effect for desaturating the contents of the framebuffer image.
*
* Broadly, this effect is achieved by reinterpreting the contents of the RGBA16 color image as indices into an IA16
* color palette that converts each color into the desaturated equivalent. More precise details can be found in inline
* comments.
*/
#include "global.h"
#include <string.h>
#include <string.h> // memset
#include <assert.h>
#include "soh/framebuffer_effects.h"
// (Note: 80 = SCREEN_HEIGHT/3, see VisMono_DrawTexture)
// This may not have been kept up-to-date with the code, 1+1+1+80*(7+2+2+3)+1+1 makes more sense
#define DLSIZE (1 + 3 + 1 + 1 + 80 * (7 + 2 + 2 + 3) + 1)
// Upstream TODO: Replace these ones they are served from other headers
#define ASSERT(cond, msg, file, line) assert(cond)
#define GPACK_IA16(i, a) (((i) << 8) | (a))
// framebuffer
// Height of the fragments the color frame buffer (CFB) is split into.
// It is the maximum amount of lines such that all rgba16 SCREEN_WIDTH-long lines fit into
// the half of TMEM dedicated to color-indexed data.
#define VISMONO_CFBFRAG_HEIGHT ((TMEM_SIZE / 2) / (SCREEN_WIDTH * G_IM_SIZ_16b_BYTES))
// Maximum size of the dlist written by `VisMono_DesaturateDList`.
// `VisMono_DesaturateDList` consistently uses `VISMONO_DLSIZE - 2` double words, so this can be 2 less.
#define VISMONO_DLSIZE (3 + SCREEN_HEIGHT / VISMONO_CFBFRAG_HEIGHT * (7 + 2 + 2 + 3) + 2 + 2)
// How much each color component contributes to the desaturated result.
// These coefficients are close to what the YUV color space defines Y (luminance) as:
// https://en.wikipedia.org/wiki/YUV#Conversion_to/from_RGB
#define VISMONO_FAC_RED 2
#define VISMONO_FAC_GREEN 4
#define VISMONO_FAC_BLUE 1
#define VISMONO_FAC_NORM (0x1F * VISMONO_FAC_RED + 0x1F * VISMONO_FAC_GREEN + 0x1F * VISMONO_FAC_BLUE)
// color framebuffer
extern u16 D_0F000000[];
void VisMono_Init(VisMono* this) {
memset(this, 0, sizeof(VisMono));
this->unk_00 = 0;
this->setScissor = false;
this->primColor.r = 255;
this->primColor.g = 255;
this->primColor.b = 255;
this->primColor.a = 255;
this->envColor.r = 0;
this->envColor.g = 0;
this->envColor.b = 0;
this->envColor.a = 0;
this->vis.type = 0;
this->vis.scissorType = VIS_NO_SETSCISSOR;
this->vis.primColor.r = 255;
this->vis.primColor.g = 255;
this->vis.primColor.b = 255;
this->vis.primColor.a = 255;
this->vis.envColor.r = 0;
this->vis.envColor.g = 0;
this->vis.envColor.b = 0;
this->vis.envColor.a = 0;
}
void VisMono_Destroy(VisMono* this) {
SYSTEM_ARENA_FREE_DEBUG(this->monoDl);
SYSTEM_ARENA_FREE(this->dList, "../z_vismono.c", 137);
}
void VisMono_UpdateTexture(VisMono* this, u16* tex) {
void VisMono_DesaturateTLUT(VisMono* this, u16* tlut) {
s32 i;
for (i = 0; i < 256; i++) {
tex[i] = ((((i >> 3 & 0x1F) * 2 + (i << 2 & 0x1F) * 4) * 0xFF / 0xD9) << 8) |
(((i >> 6 & 0x1F) * 4 + (i >> 1 & 0x1F)) * 0xFF / 0xD9);
// `tlut[i]` is a IA16 color
// `i` corresponds to either byte of a RGBA16 color RRRR_RGGG GGBB_BBBA from the color frame buffer
// The high byte I (intensity) corresponds to `i` being interpreted as the high byte RRRR_RGGG
// I = (RRRRR * FAC_RED + GGG00 * FAC_GREEN) * (255 / FAC_NORM)
// The low byte A (alpha) corresponds to `i` being interpreted as the low byte GGBB_BBBA
// A = (000GG * FAC_GREEN + BBBBB * FAC_BLUE) * (255 / FAC_NORM)
// Note: I + A = (RRRRR * FAC_RED + GGGGG * FAC_GREEN + BBBBB * FAC_BLUE) * (255 / FAC_NORM)
tlut[i] = GPACK_IA16(
((i >> 3 & 0x1F) * VISMONO_FAC_RED + (i << 2 & 0x1F) * VISMONO_FAC_GREEN) * 255 / VISMONO_FAC_NORM,
((i >> 6 & 0x1F) * VISMONO_FAC_GREEN + (i >> 1 & 0x1F) * VISMONO_FAC_BLUE) * 255 / VISMONO_FAC_NORM);
}
}
Gfx* VisMono_DrawTexture(VisMono* this, Gfx* gfx)
{
// OTRTODO
#if 1
Gfx* VisMono_DesaturateDList(VisMono* this, Gfx* gfx) {
s32 y;
s32 height = 3;
//u16* tex = D_0F000000;
u16* tex = SEG_ADDR(0xF, 0);
s32 height = VISMONO_CFBFRAG_HEIGHT;
u16* cfbFrag = D_0F000000;
gDPPipeSync(gfx++);
// `G_TT_IA16`: use color-indexed images, and IA16 palettes
gDPSetOtherMode(gfx++,
G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_IA16 | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_2CYCLE | G_PM_1PRIMITIVE,
G_AC_NONE | G_ZS_PRIM | GBL_c1(G_BL_CLR_IN, G_BL_0, G_BL_CLR_IN, G_BL_1) | G_RM_CLD_SURF2);
G_AC_NONE | G_ZS_PRIM | G_RM_PASS | G_RM_CLD_SURF2);
// First color cycle sums texel 1 alpha and texel 0 color
// By using IA16 palettes, this means summing A (from the IA16 color texel 1 maps to)
// with I (from the IA16 color texel 0 maps to)
gDPSetCombineLERP(gfx++, 1, 0, TEXEL1_ALPHA, TEXEL0, 0, 0, 0, 1, PRIMITIVE, ENVIRONMENT, COMBINED, ENVIRONMENT, 0,
0, 0, PRIMITIVE);
for (y = 0; y <= SCREEN_HEIGHT - height; y += height) {
gDPLoadTextureBlock(gfx++, tex, G_IM_FMT_CI, G_IM_SIZ_8b, SCREEN_WIDTH * 2, height, 0,
// Load a few lines of the color frame buffer
gDPLoadTextureBlock(gfx++, cfbFrag, G_IM_FMT_CI, G_IM_SIZ_8b, SCREEN_WIDTH * 2, height, 0,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD);
gDPSetTile(gfx++, G_IM_FMT_CI, G_IM_SIZ_8b, 80, 0x0, G_TX_RENDERTILE, 0, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0,
G_TX_NOMIRROR | G_TX_CLAMP, 0, 0);
gDPSetTileSize(gfx++, G_TX_RENDERTILE, (2 << 2), 0, ((SCREEN_WIDTH * 2 + 1) << 2), (2 << 2));
// Set texel 0 to be a CI8 image with width `SCREEN_WIDTH * 2` and height `VISMONO_CFBFRAG_HEIGHT`
// Its position in texture image space is shifted along +S by 2
gDPSetTile(gfx++, G_IM_FMT_CI, G_IM_SIZ_8b, SCREEN_WIDTH * 2 * G_IM_SIZ_8b_LINE_BYTES / 8, 0x0, G_TX_RENDERTILE,
0, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0);
gDPSetTileSize(gfx++, G_TX_RENDERTILE, 2 << 2, 0, (SCREEN_WIDTH * 2 + 1) << 2,
(VISMONO_CFBFRAG_HEIGHT - 1) << 2);
gDPSetTile(gfx++, G_IM_FMT_CI, G_IM_SIZ_8b, 80, 0x0, 1, 1, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0,
G_TX_NOMIRROR | G_TX_CLAMP, 0, 0);
gDPSetTileSize(gfx++, 1, (1 << 2), 0, ((SCREEN_WIDTH * 2) << 2), (2 << 2));
// Set texel 1 to be a CI8 image with width `SCREEN_WIDTH * 2` and height `VISMONO_CFBFRAG_HEIGHT`
// Its position in texture image space is shifted along +S by 1
// Note the palette index for this tile has also been incremented from 0 to 1, however the palette index is
// ignored for CI8 texture sampling.
gDPSetTile(gfx++, G_IM_FMT_CI, G_IM_SIZ_8b, SCREEN_WIDTH * 2 * G_IM_SIZ_8b_LINE_BYTES / 8, 0x0, 1, 1,
G_TX_NOMIRROR | G_TX_CLAMP, 0, 0, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0);
gDPSetTileSize(gfx++, 1, 1 << 2, 0, (SCREEN_WIDTH * 2) << 2, (VISMONO_CFBFRAG_HEIGHT - 1) << 2);
gSPTextureRectangle(gfx++, 0, y << 2, (SCREEN_WIDTH << 2), (y + height) << 2, G_TX_RENDERTILE, 2 << 5, 0,
2 << 10, 1 << 10);
tex += SCREEN_WIDTH * height;
// Draw a `SCREEN_WIDTH` wide, `height` high rectangle.
// Texture coordinate T (vertical) starts at 0 and changes by one each line (dtdy = 1)
// Texture coordinate S (horizontal) starts at 2 and changes by two each column (dsdx = 2)
// Because texel 0 is shifted by 2 and texel 1 only by 1 along +S,
// a pixel at S coordinates s = 2+2*n will look at the 2*n-th byte of texel 0 and the 2*n+1-th byte of texel 1.
// (in "s = 2+2*n" the first "2" is the starting S coordinate and the second "2" is the dsdx value)
// The 2*n-th byte of texel 0 is the high byte of the n-th RGBA16 color of the color frame buffer.
// The 2*n+1-th byte of texel 1 is the low byte of the n-th RGBA16 color of the color frame buffer.
// With the TLUT computed by `VisMono_DesaturateTLUT`:
// The 2*n-th byte of texel 0 maps to a IA16 color where the high byte I (intensity) corresponds to
// the high byte of the n-th RGBA16 color of the color frame buffer.
// The 2*n+1-th byte of texel 1 maps to a IA16 color where the low byte A (alpha) corresponds to
// the low byte of the n-th RGBA16 color of the color frame buffer.
// Since the combiner is in part set up to sum texel 0 color (I, intensity) with texel 1 alpha (A, alpha),
// the resulting color in the drawn rectangle is a desaturated color as defined by the `VISMONO_FAC_*` values.
gSPTextureRectangle(gfx++, 0, y << 2, SCREEN_WIDTH << 2, (y + height) << 2, G_TX_RENDERTILE, 2 << 5, 0, 2 << 10,
1 << 10);
cfbFrag += SCREEN_WIDTH * height;
}
gDPPipeSync(gfx++);
gSPEndDisplayList(gfx++);
#endif
return gfx;
}
void VisMono_Draw(VisMono* this, Gfx** gfxp) {
Gfx* gfx = *gfxp;
void VisMono_Draw(VisMono* this, Gfx** gfxP) {
Gfx* gfx = *gfxP;
u16* tlut;
Gfx* monoDL;
Gfx* glistpEnd;
Gfx* dList;
Gfx* dListEnd;
// SOH [Port] Implement VisMono by performing a framebuffer copy and redraw with an active
// grayscale command to set the mono color
FB_CopyToFramebuffer(&gfx, 0, gReusableFrameBuffer, false, NULL);
gDPSetGrayscaleColor(gfx++, this->vis.primColor.r, this->vis.primColor.g, this->vis.primColor.b,
this->vis.primColor.a);
gSPGrayscale(gfx++, true);
FB_DrawFromFramebuffer(&gfx, gReusableFrameBuffer, 255);
gSPGrayscale(gfx++, false);
#if 0
if (this->tlut) {
tlut = this->tlut;
} else {
tlut = Graph_DlistAlloc(&gfx, 256 * sizeof(u16));
VisMono_UpdateTexture(this, tlut);
tlut = Graph_DlistAlloc(&gfx, 256 * G_IM_SIZ_16b_BYTES);
VisMono_DesaturateTLUT(this, tlut);
}
if (this->monoDl) {
monoDL = this->monoDl;
if (this->dList) {
dList = this->dList;
} else {
monoDL = Graph_DlistAlloc(&gfx, DLSIZE * sizeof(Gfx));
glistpEnd = VisMono_DrawTexture(this, monoDL);
dList = Graph_DlistAlloc(&gfx, VISMONO_DLSIZE * sizeof(Gfx));
dListEnd = VisMono_DesaturateDList(this, dList);
if (!(glistpEnd <= monoDL + DLSIZE)) {
LOG_ADDRESS("glistp_end", glistpEnd);
LOG_ADDRESS("mono_dl", monoDL);
LOG_ADDRESS("mono_dl + (1+3+1+1+80*(7+2+2+3)+1)", monoDL + DLSIZE);
LOG_ADDRESS("(1+3+1+1+80*(7+2+2+3)+1)", DLSIZE);
if (!(dListEnd <= dList + VISMONO_DLSIZE)) {
LOG_ADDRESS("glistp_end", dListEnd);
LOG_ADDRESS("mono_dl", dList);
LOG_ADDRESS("mono_dl + (1+3+1+1+80*(7+2+2+3)+1)", dList + VISMONO_DLSIZE);
LOG_ADDRESS("(1+3+1+1+80*(7+2+2+3)+1)", VISMONO_DLSIZE);
}
assert(glistpEnd <= monoDL + DLSIZE);
ASSERT(dListEnd <= dList + VISMONO_DLSIZE, "glistp_end <= mono_dl + DLSIZE", "../z_vismono.c", 262);
}
gDPPipeSync(gfx++);
if (this->setScissor == true) {
if (this->vis.scissorType == VIS_SETSCISSOR) {
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
gDPSetColor(gfx++, G_SETPRIMCOLOR, this->primColor.rgba);
gDPSetColor(gfx++, G_SETENVCOLOR, this->envColor.rgba);
gDPSetColor(gfx++, G_SETPRIMCOLOR, this->vis.primColor.rgba);
gDPSetColor(gfx++, G_SETENVCOLOR, this->vis.envColor.rgba);
gDPLoadTLUT_pal256(gfx++, tlut);
gSPDisplayList(gfx++, monoDL);
gDPPipeSync(gfx++);
gSPDisplayList(gfx++, dList);
*gfxp = gfx;
gDPPipeSync(gfx++);
#endif
*gfxP = gfx;
}
void VisMono_DrawOld(VisMono* this) {
Gfx* glistpEnd;
Gfx* dListEnd;
if (!this->tlut) {
this->tlut = SYSTEM_ARENA_MALLOC_DEBUG(256 * sizeof(u16));
VisMono_UpdateTexture(this, this->tlut);
if (this->tlut == NULL) {
this->tlut = SYSTEM_ARENA_MALLOC(256 * G_IM_SIZ_16b_BYTES, "../z_vismono.c", 283);
VisMono_DesaturateTLUT(this, this->tlut);
}
if (!this->monoDl) {
this->monoDl = SYSTEM_ARENA_MALLOC_DEBUG(DLSIZE * sizeof(Gfx));
glistpEnd = VisMono_DrawTexture(this, this->monoDl);
assert(glistpEnd <= this->monoDl + DLSIZE);
if (this->dList == NULL) {
this->dList = SYSTEM_ARENA_MALLOC(VISMONO_DLSIZE * sizeof(Gfx), "../z_vismono.c", 289);
dListEnd = VisMono_DesaturateDList(this, this->dList);
ASSERT(dListEnd <= this->dList + VISMONO_DLSIZE, "glistp_end <= this->mono_dl + DLSIZE", "../z_vismono.c", 292);
}
}

116
soh/src/code/z_viszbuf.c Normal file
View File

@ -0,0 +1,116 @@
/**
* @file z_viszbuf.c
*
* This file implements a full-screen framebuffer effect for visualizing the z-buffer (AKA depth buffer), using either
* cycling RGBA or a single fading color.
*
* This is done by reading the z-buffer as if it were a color image, the format of which is specified by the selected
* vis type:
* - VIS_ZBUF_TYPE_IA : Produces a monotonic fade from primColor to envColor as depth increases.
* - VIS_ZBUF_TYPE_RGBA : Produces vibrant almost-periodic-looking bands.
*
* In both cases this occurs because of the format the depth information takes: it is 18-bit, and is a nonnegative
* floating-point number with
* bbb mmmmmmmmmmm dd|dd
* exponent mantissa dz value (only first 16 bits visible to CPU, the least significant 2 bits of dz are ignored)
*
* Reading z-buffer as IA16:
* bbbmmmmm mmmmmmdd
* iiiiiiii aaaaaaaa
*
* Since floating-point numbers of this format have the same ordering as their binary/hex representation, increasing
* the depth also increases the intensity in the IA16 representation and hence the interpolation parameter used to
* combine primColor and envColor. The alpha is ignored by the RenderMode.
*
* Reading z-buffer as RGBA16:
* bbbmm mmmmm mmmmd d
* rrrrr ggggg bbbbb a
*
* The red increases monotonically with the depth. The significant visible oscillation is the green component, because
* it rolls over every time the second-most-significant bit of the mantissa increments. The blue component oscillates
* too rapidly to be particularly visible (it rolls over when the 7th-most-significant bit increments). The alpha is
* again ignored by the RenderMode.
*/
#include "global.h"
// Height of the fragments the z-buffer is split into.
// It is the maximum amount of lines such that all rgba16 SCREEN_WIDTH-long lines fit into TMEM.
#define VISZBUF_ZBUFFRAG_HEIGHT (TMEM_SIZE / (SCREEN_WIDTH * G_IM_SIZ_16b_BYTES))
// z-buffer
extern u16 D_0E000000[];
/**
* Initialise to IA type with white and black as default colors.
*/
void VisZBuf_Init(VisZBuf* this) {
this->vis.type = VIS_ZBUF_TYPE_IA;
this->vis.scissorType = VIS_NO_SETSCISSOR;
this->vis.primColor.r = 255;
this->vis.primColor.g = 255;
this->vis.primColor.b = 255;
this->vis.primColor.a = 255;
// clang-format off
this->vis.envColor.r = 0; \
this->vis.envColor.g = 0; \
this->vis.envColor.b = 0; \
this->vis.envColor.a = 255;
// clang-format on
}
void VisZBuf_Destroy(VisZBuf* this) {
}
void VisZBuf_Draw(VisZBuf* this, Gfx** gfxP) {
Gfx* gfx = *gfxP;
s32 pad;
u16* zbufFrag = D_0E000000;
s32 fmt;
s32 y;
s32 height;
if (this->vis.type == VIS_ZBUF_TYPE_IA) {
fmt = G_IM_FMT_IA;
} else { // VIS_ZBUF_TYPE_RGBA
fmt = G_IM_FMT_RGBA;
}
height = VISZBUF_ZBUFFRAG_HEIGHT;
gDPPipeSync(gfx++);
// Scissoring is only required if the scissor has not been set prior.
if (this->vis.scissorType == VIS_SETSCISSOR) {
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
// No palette so can use all of TMEM.
// G_RM_OPA_SURF discards all information previously in the pixel, and the current alpha, leaving only the color
// from this filter.
gDPSetOtherMode(gfx++,
G_AD_DISABLE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | G_RM_OPA_SURF | G_RM_OPA_SURF2);
// LERP between primColor and envColor in 1-cycle mode using the z-buffer value.
gDPSetCombineLERP(gfx++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT,
PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT);
gDPSetColor(gfx++, G_SETPRIMCOLOR, this->vis.primColor.rgba);
gDPSetColor(gfx++, G_SETENVCOLOR, this->vis.envColor.rgba);
for (y = 0; y <= SCREEN_HEIGHT - height; y += height) {
// Load a few lines of the z-buffer, as many as can fit in TMEM at once.
gDPLoadTextureBlock(gfx++, zbufFrag, fmt, G_IM_SIZ_16b, SCREEN_WIDTH, height, 0, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
// Overwrite them with the calculated colors.
gSPTextureRectangle(gfx++, 0, y << 2, SCREEN_WIDTH << 2, (y + height) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10,
1 << 10);
zbufFrag += SCREEN_WIDTH * height;
}
gDPPipeSync(gfx++);
*gfxP = gfx;
}

View File

@ -181,8 +181,8 @@ void ArmsHook_Shoot(ArmsHook* this, PlayState* play) {
}
}
this->timer = 0;
Audio_PlaySoundGeneral(NA_SE_IT_ARROW_STICK_CRE, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_ARROW_STICK_CRE, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
} else if (DECR(this->timer) == 0) {
grabbed = this->grabbed;
if (grabbed != NULL) {
@ -278,12 +278,12 @@ void ArmsHook_Shoot(ArmsHook* this, PlayState* play) {
}
}
func_80865044(this);
Audio_PlaySoundGeneral(NA_SE_IT_HOOKSHOT_STICK_OBJ, &this->actor.projectedPos, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_HOOKSHOT_STICK_OBJ, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
CollisionCheck_SpawnShieldParticlesMetal(play, &this->actor.world.pos);
Audio_PlaySoundGeneral(NA_SE_IT_HOOKSHOT_REFLECT, &this->actor.projectedPos, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_IT_HOOKSHOT_REFLECT, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
} else if (CHECK_BTN_ANY(play->state.input[0].press.button, (buttonsToCheck))) {
this->timer = 0;

View File

@ -234,7 +234,7 @@ void func_8086EE40(BgBombwall* this, PlayState* play) {
func_8086EE94(this, play);
if (((this->dyna.actor.params >> 0xF) & 1) != 0) {
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
}
}
}

View File

@ -307,11 +307,11 @@ void BgBreakwall_Wait(BgBreakwall* this, PlayState* play) {
gSaveContext.cutsceneTrigger = 1;
Player_SetCsActionWithHaltedActors(play, NULL, 0x31);
}
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
if (this->dyna.actor.params < 0) {
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
Actor_Kill(&this->dyna.actor);

View File

@ -173,8 +173,8 @@ void BgDdanKd_LowerStairs(BgDdanKd* this, PlayState* play) {
func_8003555C(play, &pos1, &sBgDdanKdVelocity, &sBgDdanKdAccel);
}
Camera_AddQuake(&play->mainCamera, 0, effectStrength * 0.6f, 3);
Audio_PlaySoundGeneral(NA_SE_EV_PILLAR_SINK - SFX_FLAG, &this->dyna.actor.projectedPos, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_PILLAR_SINK - SFX_FLAG, &this->dyna.actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}

View File

@ -160,16 +160,16 @@ void BgDodoago_WaitExplosives(BgDodoago* this, PlayState* play) {
((play->roomCtx.unk_74[BGDODOAGO_EYE_RIGHT] == 255) && (this->state == BGDODOAGO_EYE_LEFT))) {
Flags_SetSwitch(play, this->dyna.actor.params & 0x3F);
this->state = 0;
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
BgDodoago_SetupAction(this, BgDodoago_OpenJaw);
OnePointCutscene_Init(play, 3380, 160, &this->dyna.actor, MAIN_CAM);
} else if (play->roomCtx.unk_74[this->state] == 0) {
OnePointCutscene_Init(play, 3065, 40, &this->dyna.actor, MAIN_CAM);
BgDodoago_SetupAction(this, BgDodoago_LightOneEye);
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
OnePointCutscene_Init(play, 3065, 20, &this->dyna.actor, MAIN_CAM);
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
sBgDodoagoTimer += 30;
return;
}
@ -247,11 +247,11 @@ void BgDodoago_OpenJaw(BgDodoago* this, PlayState* play) {
if (Math_SmoothStepToS(&this->dyna.actor.shape.rot.x, 0x1333, 110 - this->state, 0x3E8, 0x32) == 0) {
BgDodoago_SetupAction(this, BgDodoago_DoNothing);
Audio_PlaySoundGeneral(NA_SE_EV_STONE_BOUND, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_STONE_BOUND, &this->dyna.actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
} else {
Audio_PlaySoundGeneral(NA_SE_EV_STONE_STATUE_OPEN - SFX_FLAG, &this->dyna.actor.projectedPos, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_STONE_STATUE_OPEN - SFX_FLAG, &this->dyna.actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}

View File

@ -221,11 +221,11 @@ void BgGanonOtyuka_Fall(BgGanonOtyuka* this, PlayState* play) {
}
} else {
if (this->dropTimer == 1) {
Audio_PlaySoundGeneral(NA_SE_EV_STONEDOOR_STOP, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_STONEDOOR_STOP, &this->dyna.actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
} else {
Audio_PlaySoundGeneral(NA_SE_EV_BLOCKSINK - SFX_FLAG, &this->dyna.actor.projectedPos, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_BLOCKSINK - SFX_FLAG, &this->dyna.actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
Math_ApproachF(&this->dyna.actor.world.pos.y, -1000.0f, 1.0f, this->dyna.actor.speedXZ);
Math_ApproachF(&this->dyna.actor.speedXZ, 100.0f, 1.0f, 0.1f);

View File

@ -123,7 +123,7 @@ void BgGndDarkmeiro_UpdateBlockTimer(BgGndDarkmeiro* this, PlayState* play) {
} else {
this->actionFlags |= 4;
this->timer1 = 304;
Audio_PlaySoundGeneral(NA_SE_EV_RED_EYE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_RED_EYE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
@ -138,7 +138,7 @@ void BgGndDarkmeiro_UpdateBlockTimer(BgGndDarkmeiro* this, PlayState* play) {
} else {
this->actionFlags |= 8;
this->timer2 = 304;
Audio_PlaySoundGeneral(NA_SE_EV_RED_EYE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_RED_EYE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}

View File

@ -163,7 +163,7 @@ void func_8087B284(BgGndSoulmeiro* this, PlayState* play) {
if (!Flags_GetSwitch(play, (this->actor.params >> 8) & 0x3F)) {
this->actor.draw = BgGndSoulmeiro_Draw;
if (this->collider.base.acFlags & AC_HIT) {
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
this->unk_198 = 40;
this->actionFunc = func_8087AF38;
} else {

View File

@ -115,7 +115,7 @@ void func_8087B938(BgHaka* this, PlayState* play) {
player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY;
if (this->dyna.actor.params == 1) {
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
} else if (!IS_DAY && play->sceneNum == SCENE_GRAVEYARD) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_POH, this->dyna.actor.home.pos.x,
this->dyna.actor.home.pos.y, this->dyna.actor.home.pos.z, 0, this->dyna.actor.shape.rot.y, 0,
@ -124,7 +124,7 @@ void func_8087B938(BgHaka* this, PlayState* play) {
// un tss un tss
if (play->sceneNum == SCENE_GRAVEYARD && allPulled) {
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
func_800F5ACC(NA_BGM_STAFF_2);
Actor* actor2 = play->actorCtx.actorLists[ACTORCAT_BG].head;
@ -196,10 +196,10 @@ void BgHaka_Draw(Actor* thisx, PlayState* play) {
play->envCtx.adjLight1Color[0] = newColor.r;
play->envCtx.adjLight1Color[1] = newColor.g;
play->envCtx.adjLight1Color[2] = newColor.b;
D_801614B0.r = newColor.r;
D_801614B0.g = newColor.g;
D_801614B0.b = newColor.b;
D_801614B0.a = 255;
gVisMonoColor.r = newColor.r;
gVisMonoColor.g = newColor.g;
gVisMonoColor.b = newColor.b;
gVisMonoColor.a = 255;
gDPSetGrayscaleColor(POLY_OPA_DISP++, newColor.r, newColor.g, newColor.b, 255);
gSPGrayscale(POLY_OPA_DISP++, true);
}

View File

@ -242,7 +242,7 @@ void BgHakaGate_FloorClosed(BgHakaGate* this, PlayState* play) {
sBgPoEventPuzzleState = SKULL_OF_TRUTH_FOUND;
this->actionFunc = BgHakaGate_DoNothing;
} else {
func_80078884(NA_SE_SY_ERROR);
Sfx_PlaySfxCentered(NA_SE_SY_ERROR);
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GROUND_GATE_OPEN);
func_8003EBF8(play, &play->colCtx.dyna, this->dyna.bgId);
this->vTimer = 60;

View File

@ -230,6 +230,6 @@ void BgHakaShip_Draw(Actor* thisx, PlayState* play) {
sp2C.z = this->dyna.actor.world.pos.z;
SkinMatrix_Vec3fMtxFMultXYZ(&play->viewProjectionMtxF, &sp2C, &this->bellSoundPos);
func_80078914(&this->bellSoundPos, NA_SE_EV_SHIP_BELL - SFX_FLAG);
Sfx_PlaySfxAtPos(&this->bellSoundPos, NA_SE_EV_SHIP_BELL - SFX_FLAG);
}
}

View File

@ -546,7 +546,7 @@ void BgHakaTrap_Draw(Actor* thisx, PlayState* play) {
sp2C.y = this->dyna.actor.world.pos.y + 110.0f;
SkinMatrix_Vec3fMtxFMultXYZ(&play->viewProjectionMtxF, &sp2C, &this->unk_16C);
func_80078914(&this->unk_16C, NA_SE_EV_BRIDGE_CLOSE - SFX_FLAG);
Sfx_PlaySfxAtPos(&this->unk_16C, NA_SE_EV_BRIDGE_CLOSE - SFX_FLAG);
}
}

View File

@ -163,7 +163,7 @@ void BgHakaTubo_DropCollectible(BgHakaTubo* this, PlayState* play) {
if (sPotsDestroyed == 3) {
// All 3 pots destroyed
collectibleParams = -1;
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
// Drop rupees
for (i = 0; i < 9; i++) {
collectible = Item_DropCollectible(play, &spawnPos, i % 3);
@ -178,7 +178,7 @@ void BgHakaTubo_DropCollectible(BgHakaTubo* this, PlayState* play) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_FIREFLY, this->dyna.actor.world.pos.x,
this->dyna.actor.world.pos.y + 80.0f, this->dyna.actor.world.pos.z, 0,
this->dyna.actor.shape.rot.y, 0, 2, true);
func_80078884(NA_SE_SY_ERROR);
Sfx_PlaySfxCentered(NA_SE_SY_ERROR);
} else {
// Random rewards
if (CVarGetInteger(CVAR_ENHANCEMENT("NoRandomDrops"), 0)) {
@ -192,7 +192,7 @@ void BgHakaTubo_DropCollectible(BgHakaTubo* this, PlayState* play) {
} else {
collectibleParams = ITEM00_ARROWS_SMALL;
}
func_80078884(NA_SE_SY_TRE_BOX_APPEAR);
Sfx_PlaySfxCentered(NA_SE_SY_TRE_BOX_APPEAR);
}
} else if (Flags_GetCollectible(play, this->dyna.actor.params) != 0) {
// If small key already collected, drop recovery heart instead
@ -202,11 +202,11 @@ void BgHakaTubo_DropCollectible(BgHakaTubo* this, PlayState* play) {
else {
collectibleParams = ITEM00_HEART;
}
func_80078884(NA_SE_SY_TRE_BOX_APPEAR);
Sfx_PlaySfxCentered(NA_SE_SY_TRE_BOX_APPEAR);
} else {
// Drops a small key and sets a collect flag
collectibleParams = ((this->dyna.actor.params & 0x3F) << 8) | ITEM00_SMALL_KEY;
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
}
if (collectibleParams != -1) {
collectible = Item_DropCollectible(play, &spawnPos, collectibleParams);

View File

@ -376,7 +376,7 @@ void func_80888A58(BgHidanHamstep* this, PlayState* play) {
func_808884C8(this, play);
if ((this->dyna.actor.params & 0xFF) == 5) {
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
}
osSyncPrintf("B(%d)\n", this->dyna.actor.params);

View File

@ -313,7 +313,7 @@ void BgHidanKowarerukabe_Update(Actor* thisx, PlayState* play) {
SoundSource_PlaySfxAtFixedWorldPos(play, &this->dyna.actor.world.pos, 40, NA_SE_EV_WALL_BROKEN);
}
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
Actor_Kill(&this->dyna.actor);
return;
}

View File

@ -396,7 +396,7 @@ void BgHidanRock_Draw(Actor* thisx, PlayState* play) {
SkinMatrix_Vec3fMtxFMultXYZ(&play->viewProjectionMtxF, &this->dyna.actor.home.pos, &this->unk_170);
}
func_80078914(&this->unk_170, NA_SE_EV_FIRE_PILLAR - SFX_FLAG);
Sfx_PlaySfxAtPos(&this->unk_170, NA_SE_EV_FIRE_PILLAR - SFX_FLAG);
func_8088BC40(play, this);
}
}

View File

@ -428,7 +428,7 @@ void func_808911D4(BgIceShelter* this, PlayState* play) {
}
if (type == 4) {
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
}
Actor_Kill(&this->dyna.actor);

View File

@ -275,7 +275,7 @@ void BgJyaMegami_Explode(BgJyaMegami* this, PlayState* play) {
func_80033480(play, &sp8C, 100.0f, 1, 150, 100, 1);
}
if (this->explosionTimer == 60) {
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
}
if (this->explosionTimer >= 100) {
Actor_Kill(&this->dyna.actor);

View File

@ -110,7 +110,7 @@ void BgMenkuriEye_Update(Actor* thisx, PlayState* play) {
this->framesUntilDisable = 416;
if (D_8089C1A0 == 4) {
Flags_SetSwitch(play, this->actor.params);
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
}
}
if (this->framesUntilDisable == -1) {

View File

@ -475,7 +475,7 @@ void BgMizuBwall_Idle(BgMizuBwall* this, PlayState* play) {
this->dList = NULL;
BgMizuBwall_SpawnDebris(this, play);
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_WALL_BROKEN);
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
this->actionFunc = BgMizuBwall_Break;
} else if (this->dyna.actor.xzDistToPlayer < 600.0f) {
CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base);

View File

@ -218,7 +218,7 @@ void func_808A3E54(BgMoriHineri* this, PlayState* play) {
this->moriHineriObjIdx = objBankIndex;
this->dyna.actor.params ^= 1;
sBgMoriHineriNextCamIdx = MAIN_CAM;
func_80078884(NA_SE_SY_TRE_BOX_APPEAR);
Sfx_PlaySfxCentered(NA_SE_SY_TRE_BOX_APPEAR);
} else {
this->dyna.actor.draw = NULL;
this->actionFunc = func_808A3D58;

View File

@ -134,9 +134,9 @@ void BgMoriIdomizu_Main(BgMoriIdomizu* this, PlayState* play) {
BgMoriIdomizu_SetWaterLevel(play, thisx->world.pos.y);
if (this->drainTimer > 0) {
if (switchFlagSet) {
func_800788CC(NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG);
Sfx_PlaySfxCentered2(NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG);
} else {
func_800788CC(NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG);
Sfx_PlaySfxCentered2(NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG);
}
}
}

View File

@ -137,11 +137,11 @@ void BgMoriKaitenkabe_Rotate(BgMoriKaitenkabe* this, PlayState* play) {
thisx->home.rot.y -= 0x2000;
}
thisx->world.rot.y = thisx->shape.rot.y = thisx->home.rot.y;
func_800788CC(NA_SE_EV_STONEDOOR_STOP);
Sfx_PlaySfxCentered2(NA_SE_EV_STONEDOOR_STOP);
} else {
rotY = this->rotYdeg * (0x10000 / 360.0f);
thisx->world.rot.y = thisx->shape.rot.y = thisx->home.rot.y + rotY;
func_800788CC(NA_SE_EV_WALL_SLIDE - SFX_FLAG);
Sfx_PlaySfxCentered2(NA_SE_EV_WALL_SLIDE - SFX_FLAG);
}
if (fabsf(this->dyna.unk_150) > 0.001f) {
this->dyna.unk_150 = 0.0f;

View File

@ -133,7 +133,7 @@ void BgMoriRakkatenjo_Wait(BgMoriRakkatenjo* this, PlayState* play) {
}
}
if (this->timer < 20) {
func_800788CC(NA_SE_EV_BLOCKSINK - SFX_FLAG);
Sfx_PlaySfxCentered2(NA_SE_EV_BLOCKSINK - SFX_FLAG);
}
}
@ -156,7 +156,7 @@ void BgMoriRakkatenjo_Fall(BgMoriRakkatenjo* this, PlayState* play) {
} else {
if (this->bounceCount == 0) {
this->fallCount++;
func_800788CC(NA_SE_EV_STONE_BOUND);
Sfx_PlaySfxCentered2(NA_SE_EV_STONE_BOUND);
func_800AA000(SQ(thisx->yDistToPlayer), 0xFF, 0x14, 0x96);
}
thisx->world.pos.y =

View File

@ -343,7 +343,7 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, PlayState* play) {
if (amy != NULL) {
OnePointCutscene_Init(play, 3170, 30, amy, MAIN_CAM);
}
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
gSaveContext.timer1State = 0xA;
}
} else {
@ -538,7 +538,7 @@ void BgPoEvent_PaintingPresent(BgPoEvent* this, PlayState* play) {
thisx->world.pos.y - 40.0f, thisx->world.pos.z, 0, thisx->shape.rot.y, 0,
thisx->params + ((this->type - 1) << 8), true);
OnePointCutscene_Init(play, 3160, 80, thisx, MAIN_CAM);
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
} else {
Audio_PlayActorSound2(thisx, NA_SE_EN_PO_LAUGH2);

View File

@ -150,7 +150,7 @@ void func_808A9234(BgRelayObjects* this, PlayState* play) {
func_800AA000(this->dyna.actor.xyzDistToPlayerSq, 180, 20, 100);
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_STONE_BOUND);
if (this->unk_169 != play->roomCtx.curRoom.num) {
func_800788CC(NA_SE_EN_PO_LAUGH);
Sfx_PlaySfxCentered2(NA_SE_EN_PO_LAUGH);
this->timer = 5;
this->actionFunc = func_808A932C;
return;
@ -173,7 +173,7 @@ void func_808A932C(BgRelayObjects* this, PlayState* play) {
}
if (this->timer == 0) {
if (!Player_InCsMode(play)) {
func_80078884(NA_SE_OC_ABYSS);
Sfx_PlaySfxCentered(NA_SE_OC_ABYSS);
Play_TriggerRespawn(play);
this->actionFunc = BgRelayObjects_DoNothing;
}

View File

@ -50,7 +50,7 @@ const ActorInit Bg_Spot01_Idohashira_InitVars = {
};
void BgSpot01Idohashira_PlayBreakSfx1(BgSpot01Idohashira* this) {
func_80078914(&this->dyna.actor.projectedPos, NA_SE_EV_BOX_BREAK);
Sfx_PlaySfxAtPos(&this->dyna.actor.projectedPos, NA_SE_EV_BOX_BREAK);
}
void BgSpot01Idohashira_PlayBreakSfx2(BgSpot01Idohashira* this, PlayState* play) {

View File

@ -55,8 +55,8 @@ void func_808ABB84(BgSpot01Idomizu* this, PlayState* play) {
}
play->colCtx.colHeader->waterBoxes[0].ySurface = this->actor.world.pos.y;
if (this->waterHeight < this->actor.world.pos.y) {
Audio_PlaySoundGeneral(NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
Audio_PlaySoundGeneral(NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
Math_ApproachF(&this->actor.world.pos.y, this->waterHeight, 1.0f, 2.0f);
}

View File

@ -214,7 +214,7 @@ void func_808ACC34(BgSpot02Objects* this, PlayState* play) {
}
if (play->csCtx.frames == 245 || play->csCtx.frames == 351) {
func_800788CC(NA_SE_EV_LIGHTNING);
Sfx_PlaySfxCentered2(NA_SE_EV_LIGHTNING);
}
}

View File

@ -343,7 +343,7 @@ void BgSpot06Objects_LockWait(BgSpot06Objects* this, PlayState* play) {
EffectSsGSplash_Spawn(play, &this->dyna.actor.world.pos, NULL, NULL, 1, 700);
this->collider.elements->dim.worldSphere.radius = 45;
this->actionFunc = BgSpot06Objects_LockPullOutward;
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Flags_SetSwitch(play, this->switchFlag);
OnePointCutscene_Init(play, 4120, 170, &this->dyna.actor, MAIN_CAM);
} else {

View File

@ -187,7 +187,7 @@ void BgSpot08Bakudankabe_Update(Actor* thisx, PlayState* play) {
func_808B0324(this, play);
Flags_SetSwitch(play, (this->dyna.actor.params & 0x3F));
SoundSource_PlaySfxAtFixedWorldPos(play, &this->dyna.actor.world.pos, 40, NA_SE_EV_WALL_BROKEN);
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
Actor_Kill(&this->dyna.actor);
} else if (this->dyna.actor.xzDistToPlayer < 800.0f) {
CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base);

View File

@ -139,7 +139,7 @@ void BgSpot11Bakudankabe_Update(Actor* thisx, PlayState* play) {
func_808B2218(this, play);
Flags_SetSwitch(play, (this->dyna.actor.params & 0x3F));
SoundSource_PlaySfxAtFixedWorldPos(play, &D_808B2738, 40, NA_SE_EV_WALL_BROKEN);
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
Actor_Kill(&this->dyna.actor);
return;
}

View File

@ -110,7 +110,7 @@ void func_808B29F0(BgSpot11Oasis* this, PlayState* play) {
func_808B2AA8(this);
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.world.pos.x,
this->actor.world.pos.y + 40.0f, this->actor.world.pos.z, 0, 0, 0, FAIRY_SPAWNER, true);
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
}
func_808B27F0(play, this->actor.world.pos.y);
}

View File

@ -286,7 +286,7 @@ void func_808B4194(BgSpot15Rrbox* this, PlayState* play) {
Audio_PlayActorSound2(actor, NA_SE_EV_WOOD_BOUND);
}
if (func_808B3A40(this, play)) {
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
}
actor->home.pos.x = actor->world.pos.x;
actor->home.pos.z = actor->world.pos.z;

View File

@ -472,7 +472,7 @@ void func_808B5A94(BgSpot16Bombstone* this, PlayState* play) {
func_808B5240(this, play);
if (this->unk_154 == 56) {
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
}
if (this->unk_154 > 60) {

View File

@ -118,7 +118,7 @@ void BgSpot17Bakudankabe_Update(Actor* thisx, PlayState* play) {
func_808B6BC0(this, play);
Flags_SetSwitch(play, (this->dyna.actor.params & 0x3F));
SoundSource_PlaySfxAtFixedWorldPos(play, &this->dyna.actor.world.pos, 40, NA_SE_EV_WALL_BROKEN);
func_80078884(NA_SE_SY_CORRECT_CHIME);
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
Actor_Kill(&this->dyna.actor);
}
}

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