From 1acfbb633cfd9fbd78459a6c9cf5aed889e9a6e4 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Mon, 9 Jun 2025 22:41:04 +0000 Subject: [PATCH] refactor, revamp audio compass, cue when moving into walls --- .../accessible-actors/AccessibleActorList.cpp | 333 ++++++------------ .../AccessibleAudioEngine.cpp | 95 ++--- .../accessible-actors/AccessibleAudioEngine.h | 19 +- .../accessible-actors/ActorAccessibility.cpp | 151 ++++++-- .../accessible-actors/ActorAccessibility.h | 13 +- .../accessible-actors/accessibility_cues.cpp | 145 ++++---- 6 files changed, 358 insertions(+), 398 deletions(-) diff --git a/soh/soh/Enhancements/accessible-actors/AccessibleActorList.cpp b/soh/soh/Enhancements/accessible-actors/AccessibleActorList.cpp index 6299f6d93..042af4a9b 100644 --- a/soh/soh/Enhancements/accessible-actors/AccessibleActorList.cpp +++ b/soh/soh/Enhancements/accessible-actors/AccessibleActorList.cpp @@ -11,23 +11,24 @@ #include extern "C" { -#include "overlays/actors/ovl_Obj_Switch/z_obj_switch.h" #include "overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.h" +#include "overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.h" #include "overlays/actors/ovl_Boss_Goma/z_boss_goma.h" #include "overlays/actors/ovl_En_Karebaba/z_en_karebaba.h" #include "overlays/actors/ovl_En_Ba/z_en_ba.h" #include "overlays/actors/ovl_En_Box/z_en_box.h" -#include "overlays/actors/ovl_Obj_Syokudai/z_obj_syokudai.h" +#include "overlays/actors/ovl_Door_Shutter/z_door_shutter.h" #include "overlays/actors/ovl_En_Dog/z_en_dog.h" #include "overlays/actors/ovl_En_Door/z_en_door.h" +#include "overlays/actors/ovl_En_Eiyer/z_en_eiyer.h" #include "overlays/actors/ovl_En_Elf/z_en_elf.h" #include "overlays/actors/ovl_En_Fz/z_en_fz.h" -#include "overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.h" -#include "overlays/actors/ovl_En_Eiyer/z_en_eiyer.h" #include "overlays/actors/ovl_En_G_Switch/z_en_g_switch.h" -#include "overlays/actors/ovl_Door_Shutter/z_door_shutter.h" -#include "overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.h" +#include "overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.h" #include "overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.h" +#include "overlays/actors/ovl_En_Wood02/z_en_wood02.h" +#include "overlays/actors/ovl_Obj_Switch/z_obj_switch.h" +#include "overlays/actors/ovl_Obj_Syokudai/z_obj_syokudai.h" void EnBox_WaitOpen(EnBox*, PlayState*); void EnKarebaba_DeadItemDrop(EnKarebaba*, PlayState*); @@ -40,21 +41,9 @@ void EnGSwitch_SilverRupeeIdle(EnGSwitch*, PlayState*); extern u8 sBgPoEventPuzzleState; } -// User data for the general helper VA. -typedef struct { - s16 currentScene; - s8 currentRoom; - bool currentRoomClear; -} GeneralHelperData; - -typedef struct { - f32 linearVelocity; - int framesUntilChime; -} AudioCompassData; - void accessible_grotto(AccessibleActor* actor) { if ((actor->actor->params & 0x300) == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DROP_FALL, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DROP_FALL); } } @@ -68,7 +57,7 @@ void accessible_torches(AccessibleActor* actor) { if ((actor->frameCount & 31) != 0) { return; } - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_BOMB_IGNIT, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_BOMB_IGNIT); } else { if (actor->policy.volume != 1.0) { actor->policy.volume = 1.0; @@ -77,7 +66,7 @@ void accessible_torches(AccessibleActor* actor) { if ((actor->frameCount & 31) != 0) { return; } - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_BOMB_IGNIT, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_BOMB_IGNIT); } if ((actor->frameCount & 31) != 0) { return; @@ -86,9 +75,9 @@ void accessible_torches(AccessibleActor* actor) { // unlit permanent torches if ((actor->actor->params) == 8192) { if (torche->litTimer == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_BOMB_IGNIT, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_BOMB_IGNIT); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_ANUBIS_FIRE, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_ANUBIS_FIRE); } } // lit permanent torches @@ -96,7 +85,7 @@ void accessible_torches(AccessibleActor* actor) { actor->policy.volume = 0.5; actor->policy.distance = 200.0; - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_ANUBIS_FIRE, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_ANUBIS_FIRE); } } @@ -110,35 +99,35 @@ void accessible_switch(AccessibleActor* actor) { } if (scale.y >= 33.0f / 200.0f) { if (actor->play->sceneNum == 0 && actor->play->roomCtx.curRoom.num == 5 && actor->xzDistToPlayer < 20) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIAMOND_SWITCH, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIAMOND_SWITCH); } if ((actor->frameCount & 31) != 0) { return; } - ActorAccessibility_PlaySoundForActor(actor, 1, NA_SE_EV_FOOT_SWITCH, false); + ActorAccessibility_PlaySoundForActor(actor, 1, NA_SE_EV_FOOT_SWITCH); } } else if ((actor->frameCount & 31) != 0) { return; } else if ((actor->actor->params & 7) == OBJSWITCH_TYPE_FLOOR_RUSTY) { if (actor->xyzDistToPlayer < 800 && scale.y >= 33.0f / 200.0f) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_HAMMER_HIT, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_HAMMER_HIT); } } else if ((actor->actor->params & 7) == OBJSWITCH_TYPE_EYE) { if (sw->eyeTexIndex == 0) { actor->policy.aimAssist.isProvider = true; actor->policy.ydist = 1000; - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_FOOT_SWITCH, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_FOOT_SWITCH); } } else if (actor->xyzDistToPlayer < 1000) { actor->policy.aimAssist.isProvider = true; actor->policy.ydist = 1000; - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIAMOND_SWITCH, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIAMOND_SWITCH); } } void accessible_larva(AccessibleActor* actor) { if (actor->actor->bgCheckFlags == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_GOMA_BJR_EGG1, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_GOMA_BJR_EGG1); } } @@ -213,59 +202,59 @@ void accessible_area_change(AccessibleActor* actor) { return; } if (actor->play->sceneNum == SCENE_KOKIRI_FOREST && actor->pos.y < 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_HORSE_RUN_LEVEL, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_HORSE_RUN_LEVEL); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SARIA_MELODY, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SARIA_MELODY); } // kokiri forest and lost woods } else if (actor->play->sceneNum >= SCENE_DEKU_TREE_BOSS && actor->play->sceneNum <= SCENE_GANONDORF_BOSS) { return; // dont check for entrances while in boss rooms } else if (actor->play->sceneNum == SCENE_GROTTOS || actor->play->sceneNum == SCENE_FAIRYS_FOUNTAIN) { actor->policy.volume = 0.1; - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_WARP_HOLE, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_WARP_HOLE); } else if (actor->sceneIndex == SCENE_HYRULE_FIELD) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_HORSE_RUN_LEVEL, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_HORSE_RUN_LEVEL); } else if (actor->sceneIndex <= SCENE_GERUDO_TRAINING_GROUND) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_FANTOM_WARP_S, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_FANTOM_WARP_S); } else if (actor->sceneIndex >= SCENE_MARKET_ENTRANCE_DAY && actor->sceneIndex <= SCENE_MARKET_ENTRANCE_RUINS) { if (actor->play->sceneNum >= SCENE_MARKET_DAY && actor->play->sceneNum <= SCENE_MARKET_RUINS) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_HORSE_RUN_LEVEL, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_HORSE_RUN_LEVEL); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SMALL_DOG_BARK, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SMALL_DOG_BARK); } } else if (actor->sceneIndex >= SCENE_BACK_ALLEY_DAY && actor->sceneIndex <= SCENE_MARKET_NIGHT) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SMALL_DOG_BARK, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SMALL_DOG_BARK); } else if (actor->sceneIndex >= SCENE_MARKET_RUINS && actor->sceneIndex <= SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_STONE_BOUND, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_STONE_BOUND); } else if (actor->play->sceneNum == SCENE_TEMPLE_OF_TIME) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SMALL_DOG_BARK, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SMALL_DOG_BARK); } else if (actor->sceneIndex == SCENE_CASTLE_COURTYARD_GUARDS_DAY || actor->sceneIndex == SCENE_CASTLE_COURTYARD_GUARDS_NIGHT) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_MUSI_SINK, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_MUSI_SINK); } else if (actor->sceneIndex == SCENE_KAKARIKO_VILLAGE) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_CHICKEN_CRY_M, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_CHICKEN_CRY_M); } else if (actor->sceneIndex == SCENE_GRAVEYARD) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_PO_APPEAR, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_PO_APPEAR); } else if (actor->sceneIndex == SCENE_ZORAS_RIVER || actor->sceneIndex == SCENE_ZORAS_DOMAIN || actor->sceneIndex == SCENE_ZORAS_FOUNTAIN) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_RIVER_STREAM_S, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_RIVER_STREAM_S); } else if (actor->sceneIndex == SCENE_SACRED_FOREST_MEADOW) { } else if (actor->sceneIndex == SCENE_LAKE_HYLIA) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_WATER_WALL, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_WATER_WALL); } else if (actor->sceneIndex == SCENE_GERUDO_VALLEY || actor->sceneIndex == SCENE_GERUDOS_FORTRESS) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_PL_CRAWL_SAND, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_PL_CRAWL_SAND); } else if (actor->sceneIndex == SCENE_DESERT_COLOSSUS || actor->sceneIndex == SCENE_HAUNTED_WASTELAND) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SAND_STORM, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SAND_STORM); } else if (actor->sceneIndex == SCENE_OUTSIDE_GANONS_CASTLE || actor->sceneIndex == SCENE_HYRULE_CASTLE) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_BRIDGE_OPEN, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_BRIDGE_OPEN); } else if (actor->sceneIndex == SCENE_DEATH_MOUNTAIN_TRAIL) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_DODO_K_ROLL, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_DODO_K_ROLL); } else if (actor->sceneIndex == SCENE_DEATH_MOUNTAIN_CRATER) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_DODO_K_LAVA, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_DODO_K_LAVA); } else if (actor->sceneIndex == SCENE_GORON_CITY) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_DARUNIA_HIT_BREAST, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_DARUNIA_HIT_BREAST); } else if (actor->sceneIndex == SCENE_LON_LON_RANCH) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_COW_CRY, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_COW_CRY); } else if (actor->sceneIndex >= SCENE_DEKU_TREE_BOSS && actor->sceneIndex <= SCENE_GANONDORF_BOSS) { return; } else { @@ -273,7 +262,7 @@ void accessible_area_change(AccessibleActor* actor) { if (actor->play->sceneNum == SCENE_GRAVEYARD) { actor->policy.ydist = 0; } - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_OC_DOOR_OPEN, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_OC_DOOR_OPEN); } } @@ -284,43 +273,43 @@ void accessible_en_guard(AccessibleActor* actor) { fabs(actor->actor->world.pos.z - player->actor.world.pos.z)) { if (fabs(actor->actor->shape.rot.y - 16384) < 1000) { if (actor->actor->world.pos.x < player->actor.world.pos.x) { - ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx, false); + ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx); ActorAccessibility_SetSoundPitch(actor, 0, 2.0); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx, false); + ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx); ActorAccessibility_SetSoundPitch(actor, 0, 0.2); } } else if ((actor->actor->shape.rot.y + 16384) < 1000) { if (actor->actor->world.pos.x < player->actor.world.pos.x) { - ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx, false); + ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx); ActorAccessibility_SetSoundPitch(actor, 0, 0.2); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx, false); + ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx); ActorAccessibility_SetSoundPitch(actor, 0, 2.0); } } else { - ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx, false); + ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx); ActorAccessibility_SetSoundPitch(actor, 0, 1.0); } } else { if (fabs(actor->actor->shape.rot.y) < 1000) { if (actor->actor->world.pos.z < player->actor.world.pos.z) { - ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx, false); + ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx); ActorAccessibility_SetSoundPitch(actor, 0, 2.0); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx, false); + ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx); ActorAccessibility_SetSoundPitch(actor, 0, 0.2); } } else if (fabs(actor->actor->shape.rot.y + 32768) < 1000) { if (actor->actor->world.pos.z < player->actor.world.pos.z) { - ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx, false); + ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx); ActorAccessibility_SetSoundPitch(actor, 0, 0.2); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx, false); + ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx); ActorAccessibility_SetSoundPitch(actor, 0, 2.0); } } else { - ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx, false); + ActorAccessibility_PlaySoundForActor(actor, 0, guardsfx); ActorAccessibility_SetSoundPitch(actor, 0, 1.0); } } @@ -330,7 +319,7 @@ void accessible_en_dogs(AccessibleActor* actor) { EnDog* dog = (EnDog*)actor->actor; if (EnDog_CanFollow(dog, actor->play) == 1) { dog->actionFunc = EnDog_FollowPlayer; - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIAMOND_SWITCH, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIAMOND_SWITCH); ActorAccessibility_SetSoundPitch(actor, 0, 1.0); } if ((actor->frameCount & 31) != 0) { @@ -338,11 +327,11 @@ void accessible_en_dogs(AccessibleActor* actor) { } if (actor->actor->params == 608 || actor->actor->params == 336 || actor->actor->params == 304 || actor->actor->params == 3088 || actor->actor->params == 2576 || actor->actor->params < 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SMALL_DOG_BARK, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SMALL_DOG_BARK); ActorAccessibility_SetSoundPitch(actor, 0, 2.0); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SMALL_DOG_BARK, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_SMALL_DOG_BARK); ActorAccessibility_SetSoundPitch(actor, 0, 0.5); } } @@ -350,7 +339,7 @@ void accessible_en_dogs(AccessibleActor* actor) { void accessible_goma(AccessibleActor* actor) { BossGoma* goma = (BossGoma*)actor->actor; if (goma->visualState == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIAMOND_SWITCH, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIAMOND_SWITCH); } } @@ -360,7 +349,7 @@ void accessible_sticks(AccessibleActor* actor) { if (baba->actionFunc != EnKarebaba_DeadItemDrop) return; if (actor->actor->flags == 80) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_NUTS_DAMAGE, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_NUTS_DAMAGE); } } @@ -368,112 +357,10 @@ void accessible_cucco(AccessibleActor* actor) { if (actor->actor->params == 14) { } else if (actor->actor->params == 13) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_CHICKEN_CRY_N, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_CHICKEN_CRY_N); ActorAccessibility_SetSoundPitch(actor, 0, 1.5); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_CHICKEN_CRY_N, false); - } -} - -bool accessible_general_helper_init(AccessibleActor* actor) { - GeneralHelperData* data = (GeneralHelperData*)malloc(sizeof(GeneralHelperData)); - if (data == nullptr) - return false; - data->currentRoom = -1; - data->currentRoomClear = false; - data->currentScene = -1; - - actor->userData = data; - return true; -} - -void accessible_general_helper_cleanup(AccessibleActor* actor) { - free(actor->userData); - actor->userData = nullptr; -} - -void accessible_va_general_helper(AccessibleActor* actor) { - GeneralHelperData* data = (GeneralHelperData*)actor->userData; - if (data->currentScene == actor->play->sceneNum && data->currentRoom != actor->play->roomCtx.curRoom.num) { - ActorAccessibility_AnnounceRoomNumber(actor->play); - data->currentRoom = actor->play->roomCtx.curRoom.num; - data->currentRoomClear = Flags_GetClear(actor->play, data->currentRoom); - } - if (data->currentScene != actor->play->sceneNum) { - ActorAccessibility_InterpretCurrentScene(actor->play); - data->currentScene = actor->play->sceneNum; - data->currentRoom = actor->play->roomCtx.curRoom.num; - data->currentRoomClear = Flags_GetClear(actor->play, data->currentRoom); - } - // Report when a room is completed. - if (!data->currentRoomClear && Flags_GetClear(actor->play, data->currentRoom)) { - data->currentRoomClear = Flags_GetClear(actor->play, data->currentRoom); - ActorAccessibility_AnnounceRoomNumber(actor->play); - } -} - -bool accessible_audio_compass_init(AccessibleActor* actor) { - AudioCompassData* data = (AudioCompassData*)malloc(sizeof(AudioCompassData)); - if (data == nullptr) - return false; - data->linearVelocity = 0; - data->framesUntilChime = 0; - - actor->userData = data; - return true; -} - -void accessible_audio_compass_cleanup(AccessibleActor* actor) { - free(actor->userData); -} - -void accessible_audio_compass(AccessibleActor* actor) { - Player* player = GET_PLAYER(actor->play); - OSContPad* trackerButtonsPressed = - std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetControlDeck())->GetPads(); - AudioCompassData* data = (AudioCompassData*)actor->userData; - bool compassCombo = trackerButtonsPressed != nullptr && trackerButtonsPressed[0].button & BTN_DDOWN && - trackerButtonsPressed[0].button & BTN_L; - actor->pos = player->actor.world.pos; - actor->pos.z -= 50; - - if (data->framesUntilChime > 0) - data->framesUntilChime--; - if (compassCombo && data->framesUntilChime <= 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, actor->policy.sound, false); - data->framesUntilChime = 30; - } -} - -void accessible_stick_warning(AccessibleActor* actor) { - Player* player = GET_PLAYER(actor->play); - actor->pos = player->actor.world.pos; - actor->pos.z -= 50; - if (fabs(player->unk_860 - 25) < 24.0 && player->heldItemId == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_SY_WARNING_COUNT_N, false); - } - - if (Player_HoldsHookshot(player) && player->heldActor != NULL && player->actor.scale.y >= 0.0f && - (player->stateFlags1 & PLAYER_STATE1_FIRST_PERSON)) { - CollisionPoly* colPoly; - s32 bgId; - Vec3f hookshotEnd; - Vec3f firstHit; - f32 hookshotLength = ((player->heldItemAction == PLAYER_IA_HOOKSHOT) ? 380.0f : 770.0f) * - CVarGetFloat(CVAR_CHEAT("HookshotReachMultiplier"), 1.0f); - hookshotEnd.x = player->heldActor->world.pos.x + Math_SinS(player->heldActor->world.rot.y) * - Math_SinS(-player->heldActor->world.rot.x) * - hookshotLength; - hookshotEnd.y = player->heldActor->world.pos.y + Math_SinS(-player->heldActor->world.rot.x) * hookshotLength; - hookshotEnd.z = player->heldActor->world.pos.z + Math_CosS(player->heldActor->world.rot.y) * - Math_CosS(-player->heldActor->world.rot.x) * - hookshotLength; - if (BgCheck_AnyLineTest3(&actor->play->colCtx, &player->heldActor->world.pos, &hookshotEnd, &firstHit, &colPoly, - 1, 1, 1, 1, &bgId)) { - if (SurfaceType_IsHookshotSurface(&actor->play->colCtx, colPoly, bgId)) { - ActorAccessibility_PlaySoundForActor(actor, 1, NA_SE_IT_HOOKSHOT_STICK_OBJ, false); - } - } + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_CHICKEN_CRY_N); } } @@ -602,14 +489,21 @@ void ActorAccessibility_InitActors() { ActorAccessibility_AddSupportedActor(ACTOR_EN_NIW, policy); ActorAccessibility_InitPolicy(&policy, "Bush", NA_SE_PL_PULL_UP_PLANT); ActorAccessibility_AddSupportedActor(ACTOR_EN_KUSA, policy); - ActorAccessibility_InitPolicy(&policy, "Trees", NA_SE_EV_TREE_CUT); + ActorAccessibility_InitPolicy(&policy, "Trees", [](AccessibleActor* actor) { + EnWood02* wood = (EnWood02*)actor->actor; + if (wood->actor.params <= WOOD_TREE_KAKARIKO_ADULT) { + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_TREE_CUT); + } else if (wood->actor.params < WOOD_LEAF_GREEN) { + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_TREE_SWING); + } + }); ActorAccessibility_AddSupportedActor(ACTOR_EN_WOOD02, policy); ActorAccessibility_InitPolicy(&policy, "Scarecrow Spawn", [](AccessibleActor* actor) { if ((actor->frameCount & 63) == 0) { EnKakasi2* kakasi = (EnKakasi2*)actor->actor; actor->policy.distance = kakasi->maxSpawnDistance.x; actor->policy.ydist = kakasi->maxSpawnDistance.y; - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_KAKASHI_SWING, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_KAKASHI_SWING); } }); policy.distance = 2000; @@ -629,7 +523,7 @@ void ActorAccessibility_InitActors() { size = 30; // large } if (!(treasureFlag >= 20 && treasureFlag < 32)) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_TBOX_UNLOCK, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_TBOX_UNLOCK); } // Only chests that are "waiting to be opened" should play a sound. Chests which have not yet appeared (because // some enemy has not been killed, switch has not been hit, etc) will not be in this action mode. @@ -649,7 +543,7 @@ void ActorAccessibility_InitActors() { if ((xdist - size / 2) < 0) { ActorAccessibility_SetSoundPitch(actor, 0, 0.5); } else if ((xdist + size / 2) > 0 && zdist < size / 2 && xdist < 150.0) { - ActorAccessibility_PlaySoundForActor(actor, 1, NA_SE_EV_DIAMOND_SWITCH, false); + ActorAccessibility_PlaySoundForActor(actor, 1, NA_SE_EV_DIAMOND_SWITCH); } }); policy.pitch = 1.1; @@ -692,7 +586,7 @@ void ActorAccessibility_InitActors() { if (actor->actor->category == ACTORCAT_ITEMACTION) { s16 params = actor->actor->params; if (params == FAIRY_HEAL || params == FAIRY_HEAL_TIMED || params == FAIRY_HEAL_BIG) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_BUTTERFRY_TO_FAIRY, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_BUTTERFRY_TO_FAIRY); } } }); @@ -710,7 +604,7 @@ void ActorAccessibility_InitActors() { ActorAccessibility_AddSupportedActor(ACTOR_EN_PO_DESERT, policy); ActorAccessibility_InitPolicy(&policy, "flag pole", [](AccessibleActor* actor) { if ((actor->frameCount & 31) == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_FLUTTER_FLAG, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_FLUTTER_FLAG); } }); policy.aimAssist.isProvider = true; @@ -756,9 +650,9 @@ void ActorAccessibility_InitActors() { ActorAccessibility_InitPolicy(&policy, "Shutter Door", [](AccessibleActor* actor) { DoorShutter* doorShutter = (DoorShutter*)actor->actor; if (doorShutter->doorType == SHUTTER_KEY_LOCKED && !Flags_GetSwitch(actor->play, actor->actor->params & 0x3F)) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_CHAIN_KEY_UNLOCK_B, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_CHAIN_KEY_UNLOCK_B); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_OC_DOOR_OPEN, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_OC_DOOR_OPEN); } }); policy.n = 30; @@ -781,7 +675,7 @@ void ActorAccessibility_InitActors() { actor->policy.aimAssist.isProvider = true; } if ((actor->frameCount & 31) == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIAMOND_SWITCH, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIAMOND_SWITCH); } }); policy.n = 1; @@ -792,7 +686,7 @@ void ActorAccessibility_InitActors() { ActorAccessibility_InitPolicy(&policy, "Jabu Object", [](AccessibleActor* actor) { if ((actor->actor->params & 0xFF) == 2 && actor->xzDistToPlayer > 50) { // Jabu Elevator - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_PL_LAND_LADDER, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_PL_LAND_LADDER); } }); policy.n = 1; @@ -820,10 +714,10 @@ void ActorAccessibility_InitActors() { if ((actor->actor->params) == 0) { actor->policy.ydist = 1000; actor->policy.distance = 1000; - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_OCTAROCK_ROCK, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_OCTAROCK_ROCK); } else if ((actor->actor->params) == 1) { actor->policy.ydist = 1000; - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_PL_DAMAGE, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_PL_DAMAGE); } }); policy.distance = 1000; @@ -834,15 +728,15 @@ void ActorAccessibility_InitActors() { actor->policy.distance = 400; if ((actor->frameCount & 31) == 0) { ActorAccessibility_SetSoundPitch(actor, 0, 0.5f + 1.0f * po->index); - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_PO_APPEAR, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_PO_APPEAR); } } else if (po->type == 1) { actor->policy.distance = 300; if ((actor->frameCount & 31) == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_TRAP_BOUND, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_TRAP_BOUND); } } else if (po->index == sBgPoEventPuzzleState && (actor->frameCount & 63) == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_PO_CRY, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_PO_CRY); } }); policy.aimAssist.isProvider = true; @@ -872,19 +766,19 @@ void ActorAccessibility_InitActors() { ActorAccessibility_AddSupportedActor(ACTOR_OBJ_LIFT, policy); ActorAccessibility_InitPolicy(&policy, "Ladder in Slingshot Room", [](AccessibleActor* actor) { if (actor->actor->params == 1) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_PL_LAND_LADDER, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_PL_LAND_LADDER); } }); ActorAccessibility_AddSupportedActor(ACTOR_BG_YDAN_MARUTA, policy); ActorAccessibility_InitPolicy(&policy, "231 dekus", [](AccessibleActor* actor) { if (actor->actor->params == 1) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_NUTS_FAINT, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_NUTS_FAINT); ActorAccessibility_SetSoundPitch(actor, 0, 1.0); } else if (actor->actor->params == 2) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_NUTS_FAINT, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_NUTS_FAINT); ActorAccessibility_SetSoundPitch(actor, 0, 0.5); } else if (actor->actor->params == 3) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_NUTS_FAINT, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_NUTS_FAINT); ActorAccessibility_SetSoundPitch(actor, 0, 1.5); } }); @@ -900,7 +794,7 @@ void ActorAccessibility_InitActors() { ActorAccessibility_InitPolicy(&policy, "Blue Fire", [](AccessibleActor* actor) { if (actor->actor->params == -1) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_FLAME, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_FLAME); } }); policy.n = 60; @@ -918,7 +812,8 @@ void ActorAccessibility_InitActors() { ActorAccessibility_AddSupportedActor(ACTOR_BG_ICE_SHELTER, policy); ActorAccessibility_InitPolicy(&policy, "Statue Eye", [](AccessibleActor* actor) { - actor->policy.aimAssist.isProvider = ABS((s16)(actor->actor->yawTowardsPlayer - actor->actor->shape.rot.y)) < 0x2000; + actor->policy.aimAssist.isProvider = + ABS((s16)(actor->actor->yawTowardsPlayer - actor->actor->shape.rot.y)) < 0x2000; }); policy.n = 1; policy.ydist = 500; @@ -927,9 +822,9 @@ void ActorAccessibility_InitActors() { ActorAccessibility_InitPolicy(&policy, "uninteractable rocks in kokiri forest", [](AccessibleActor* actor) { if (actor->actor->params == 1) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_OCTAROCK_ROCK, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_OCTAROCK_ROCK); } else if (actor->actor->params == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIG_UP, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_DIG_UP); } }); ActorAccessibility_AddSupportedActor(ACTOR_OBJ_HANA, policy); @@ -944,9 +839,9 @@ void ActorAccessibility_InitActors() { ActorAccessibility_InitPolicy(&policy, "Big Skulltula", [](AccessibleActor* actor) { s16 angleTowardsLink = ABS((s16)(actor->actor->yawTowardsPlayer - actor->actor->shape.rot.y)); if (angleTowardsLink >= 0x3FFC) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_VO_ST_DAMAGE, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_VO_ST_DAMAGE); } else if ((actor->frameCount & 63) == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_STALTU_LAUGH, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_STALTU_LAUGH); } }); policy.ydist = 100; @@ -965,9 +860,9 @@ void ActorAccessibility_InitActors() { if (actionFunc == EnEiyer_Die || actionFunc == EnEiyer_Dead) { ActorAccessibility_StopAllSoundsForActor(actor); } else if (GET_PLAYER(actor->play)->actor.world.pos.y > actor->actor->world.pos.y - 8) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_FISHING_REEL_SLOW, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_FISHING_REEL_SLOW); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_FISHING_REEL_HIGH, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_IT_FISHING_REEL_HIGH); } }); policy.n = 1; @@ -983,7 +878,7 @@ void ActorAccessibility_InitActors() { ActorAccessibility_InitPolicy(&policy, "tentacle", [](AccessibleActor* actor) { if (actor->actor->params < EN_BA_DEAD_BLOB) { actor->policy.volume = 2.5 - (actor->actor->world.pos.y - actor->actor->home.pos.y) / 200.0; - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_OWL_FLUTTER, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_OWL_FLUTTER); } }); policy.distance = 1500; @@ -995,7 +890,7 @@ void ActorAccessibility_InitActors() { ActorAccessibility_InitPolicy(&policy, "freezard", [](AccessibleActor* actor) { EnFz* fz = (EnFz*)actor->actor; if (fz->state != 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_FREEZAD_DEAD, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EN_FREEZAD_DEAD); } }); policy.n = 20; @@ -1016,7 +911,7 @@ void ActorAccessibility_InitActors() { : actor->xzDistToPlayer < 200 ? 31 : 63; if ((actor->frameCount & freq) == 0) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_BOMB_DROP_WATER, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_BOMB_DROP_WATER); } } }); @@ -1039,7 +934,7 @@ void ActorAccessibility_InitActors() { if ((actor->frameCount & 31) == 0) { EnGSwitch* gswitch = (EnGSwitch*)actor->actor; if (gswitch->actionFunc == EnGSwitch_SilverRupeeIdle) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_FIVE_COUNT_LUPY, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_FIVE_COUNT_LUPY); } } }); @@ -1058,15 +953,15 @@ void ActorAccessibility_InitActors() { actor->pos.y = waterLoc; } if (actor->yDistToPlayer < 80) - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_PL_LAND_LADDER, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_PL_LAND_LADDER); }); policy.pitch = 1.3; ActorAccessibility_AddSupportedActor(VA_CLIMB, policy); ActorAccessibility_InitPolicy(&policy, "Door", [](AccessibleActor* actor) { if (((actor->actor->params >> 7) & 7) == DOOR_LOCKED) { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_CHAIN_KEY_UNLOCK_B, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_EV_CHAIN_KEY_UNLOCK_B); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_OC_DOOR_OPEN, false); + ActorAccessibility_PlaySoundForActor(actor, 0, NA_SE_OC_DOOR_OPEN); } }); policy.n = 30; @@ -1082,35 +977,11 @@ void ActorAccessibility_InitActors() { policy.distance = 1000; policy.pitch = 1.7; ActorAccessibility_AddSupportedActor(VA_MARKER, policy); - ActorAccessibility_InitPolicy(&policy, "Stick Burnout Warning", accessible_stick_warning); - policy.n = 1; - policy.runsAlways = true; - ActorAccessibility_AddSupportedActor(VA_STICK_WARNING, policy); - ActorAccessibility_InitPolicy(&policy, "System general helper", accessible_va_general_helper); - policy.n = 1; - policy.cleanupUserData = accessible_general_helper_cleanup; - policy.initUserData = accessible_general_helper_init; - policy.runsAlways = true; - ActorAccessibility_AddSupportedActor(VA_GENERAL_HELPER, policy); - ActorAccessibility_InitPolicy(&policy, "Audio Compass", accessible_audio_compass); - policy.n = 1; - policy.cleanupUserData = accessible_audio_compass_cleanup; - policy.initUserData = accessible_audio_compass_init; - policy.runsAlways = true; - policy.sound = NA_SE_EV_SHIP_BELL; // Setting this here so it's easy to change if we ever decide to change it. - policy.pitch = 0.5; - ActorAccessibility_AddSupportedActor(VA_AUDIO_COMPASS, policy); - - // Now query a list of virtual actors for a given location (scene and room number). + // Virtual actors for a given location (scene and room number). VirtualActorList* list = (VirtualActorList*)ActorAccessibility_GetVirtualActorList(EVERYWHERE, 0); AccessibleActor* temp; - // Now place the actor. - ActorAccessibility_AddVirtualActor(list, VA_GENERAL_HELPER, { 0, 0, 0 }); - ActorAccessibility_AddVirtualActor(list, VA_AUDIO_COMPASS, { 0, 0, 0 }); - ActorAccessibility_AddVirtualActor(list, VA_STICK_WARNING, { 0, 0, 0 }); - list = ActorAccessibility_GetVirtualActorList(SCENE_KOKIRI_FOREST, 0); ActorAccessibility_AddVirtualActor(list, VA_CRAWLSPACE, { -784, 120, 1046 }); ActorAccessibility_AddVirtualActor(list, VA_MARKER, { 2146, 1, -142.8 }); diff --git a/soh/soh/Enhancements/accessible-actors/AccessibleAudioEngine.cpp b/soh/soh/Enhancements/accessible-actors/AccessibleAudioEngine.cpp index 06bf57295..36425fc01 100644 --- a/soh/soh/Enhancements/accessible-actors/AccessibleAudioEngine.cpp +++ b/soh/soh/Enhancements/accessible-actors/AccessibleAudioEngine.cpp @@ -17,7 +17,6 @@ int AudioPlayer_GetDesiredBuffered(); #include #include #include -#include enum AAE_COMMANDS { AAE_START = 0, @@ -50,8 +49,7 @@ static float computeGain(SoundExtras* extras) { gain -= lerp_aae(0, leftover, normDist); return gain; } -// Borrow the pan calculation from the game itself. Todo: this is technical debt, so copy/ revise it or something at -// some point. +// Borrow pan calculation from game itself. Todo: this is technical debt, so copy/revise or something extern "C" int8_t Audio_ComputeSoundPanSigned(float x, float z, uint8_t token); static void positioner_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut) { @@ -275,14 +273,17 @@ void AccessibleAudioEngine::doPlaySound(SoundAction& action) { MA_SOUND_FLAG_NO_SPATIALIZATION | MA_SOUND_FLAG_NO_DEFAULT_ATTACHMENT, NULL, NULL, &sound->sound); if (result != MA_SUCCESS) { - SPDLOG_ERROR("failed to play sound: {}", ma_result_description(result)); return; } - initSoundExtras(sound); - ma_sound_set_looping(&sound->sound, action.looping); - // We actually attach the extras to the engine, not the sound itself. - ma_node_attach_output_bus(&sound->extras, 0, ma_node_graph_get_endpoint(&engine.nodeGraph), 0); + if (action.handle != 0) { + initSoundExtras(sound); + // We actually attach the extras to the engine, not the sound itself. + ma_node_attach_output_bus(&sound->extras, 0, ma_node_graph_get_endpoint(&engine.nodeGraph), 0); + } else { + sound->extras.base.pNodeGraph = NULL; + ma_node_attach_output_bus(&sound->sound, 0, ma_node_graph_get_endpoint(&engine.nodeGraph), 0); + } ma_sound_start(&sound->sound); @@ -295,6 +296,7 @@ void AccessibleAudioEngine::doStopSound(SoundAction& action) { return; destroySound(slot); } + void AccessibleAudioEngine::doStopAllSounds(SoundAction& action) { auto it = sounds.find(action.handle); if (it == sounds.end()) @@ -306,6 +308,7 @@ void AccessibleAudioEngine::doStopAllSounds(SoundAction& action) { } sounds.erase(it); } + void AccessibleAudioEngine::doSetPitch(SoundAction& action) { SoundSlot* slot = findSound(action); if (slot == NULL) @@ -323,18 +326,21 @@ void AccessibleAudioEngine::doSetPitchBehindModifier(SoundAction& action) { return; slot->extras.pitchBehindModifier = action.pitch; } + void AccessibleAudioEngine::doSetVolume(SoundAction& action) { SoundSlot* slot = findSound(action); if (slot == NULL) return; ma_sound_set_volume(&slot->sound, action.pitch); } + void AccessibleAudioEngine::doSetPan(SoundAction& action) { SoundSlot* slot = findSound(action); if (slot == NULL) return; ma_sound_set_pan(&slot->sound, action.pan); } + void AccessibleAudioEngine::doSetFilter(SoundAction& action) { SoundSlot* slot = findSound(action); if (slot == NULL) @@ -344,12 +350,14 @@ void AccessibleAudioEngine::doSetFilter(SoundAction& action) { lerp_aae(0.0, AAE_SAMPLE_RATE / 2, action.cutoff), AAE_LPF_ORDER); ma_lpf_reinit(&config, &slot->extras.filter); } + void AccessibleAudioEngine::doSeekSound(SoundAction& action) { SoundSlot* slot = findSound(action); if (slot == NULL) return; ma_sound_seek_to_pcm_frame(&slot->sound, action.offset); } + void AccessibleAudioEngine::doSetSoundPos(SoundAction& action) { SoundSlot* slot = findSound(action); if (slot == NULL) @@ -366,28 +374,31 @@ void AccessibleAudioEngine::doSetSoundPos(SoundAction& action) { } void AccessibleAudioEngine::garbageCollect() { for (auto i = sounds.begin(); i != sounds.end();) { - int deadSlots = 0; + bool deadSlots = true; for (int x = 0; x < AAE_SLOTS_PER_HANDLE; x++) { - if (!i->second[x].active) - deadSlots++; - else if (!ma_sound_is_playing(&i->second[x].sound)) { - destroySound(&i->second[x]); - i->second[x].active = false; - deadSlots++; + if (i->second[x].active) { + if (!ma_sound_is_playing(&i->second[x].sound)) { + destroySound(&i->second[x]); + } else { + deadSlots = false; + } } } - if (deadSlots == AAE_SLOTS_PER_HANDLE) // Entire batch is garbage. + if (deadSlots) { i = sounds.erase(i); - else + } else { i++; + } } framesUntilGC = AAE_GC_INTERVAL; } + void AccessibleAudioEngine::processAudioJobs() { ma_job job; while (ma_resource_manager_next_job(&resourceManager, &job) == MA_SUCCESS) ma_job_process(&job); } + bool AccessibleAudioEngine::initSoundExtras(SoundSlot* slot) { ma_node_config config = ma_node_config_init(); config.inputBusCount = 1; @@ -412,15 +423,18 @@ bool AccessibleAudioEngine::initSoundExtras(SoundSlot* slot) { slot->extras.cutoff = 1.0f; slot->extras.pitch = 1.0f; slot->extras.pitchBehindModifier = 0.0f; - // ma_node_attach_output_bus(&slot->sound, 0, &slot->extras.filter, 0); ma_node_attach_output_bus(&slot->sound, 0, &slot->extras, 0); return true; } void AccessibleAudioEngine::destroySound(SoundSlot* slot) { - ma_node_detach_all_output_buses(&slot->extras); - ma_sound_uninit(&slot->sound); - ma_gainer_uninit(&slot->extras.gainer, NULL); + if (slot->extras.base.pNodeGraph != NULL) { + ma_node_detach_all_output_buses(&slot->extras); + ma_sound_uninit(&slot->sound); + ma_gainer_uninit(&slot->extras.gainer, NULL); + } else { + ma_sound_uninit(&slot->sound); + } slot->active = false; } @@ -453,6 +467,7 @@ AccessibleAudioEngine::AccessibleAudioEngine() { framesUntilGC = AAE_GC_INTERVAL; thread = std::thread(&AccessibleAudioEngine::runThread, this); } + AccessibleAudioEngine::~AccessibleAudioEngine() { // Place a terminate command on the top of the pile, then wait for thread to die. SoundAction action; @@ -461,6 +476,7 @@ AccessibleAudioEngine::~AccessibleAudioEngine() { thread.join(); destroy(); } + void AccessibleAudioEngine::mix(int16_t* ogBuffer, uint32_t nFrames) { float sourceChunk[AAE_MIX_CHUNK_SIZE * AAE_CHANNELS]; float mixedChunk[AAE_MIX_CHUNK_SIZE * AAE_CHANNELS]; @@ -489,19 +505,18 @@ void AccessibleAudioEngine::mix(int16_t* ogBuffer, uint32_t nFrames) { } } -void AccessibleAudioEngine::playSound(uintptr_t handle, int slot, const char* path, bool looping) { - if (slot < 0 || slot >= AAE_SLOTS_PER_HANDLE) +void AccessibleAudioEngine::playSound(uintptr_t handle, uint8_t slot, const char* path) { + if (slot >= AAE_SLOTS_PER_HANDLE) return; SoundAction& action = getNextOutgoingSoundAction(); action.handle = handle; action.slot = slot; action.command = AAE_START; action.path = path; - action.looping = looping; } -void AccessibleAudioEngine::stopSound(uintptr_t handle, int slot) { - if (slot < 0 || slot >= AAE_SLOTS_PER_HANDLE) +void AccessibleAudioEngine::stopSound(uintptr_t handle, uint8_t slot) { + if (slot >= AAE_SLOTS_PER_HANDLE) return; SoundAction& action = getNextOutgoingSoundAction(); action.command = AAE_STOP; @@ -515,8 +530,8 @@ void AccessibleAudioEngine::stopAllSounds(uintptr_t handle) { action.handle = handle; } -void AccessibleAudioEngine::setPitch(uintptr_t handle, int slot, float pitch) { - if (slot < 0 || slot >= AAE_SLOTS_PER_HANDLE) +void AccessibleAudioEngine::setPitch(uintptr_t handle, uint8_t slot, float pitch) { + if (slot >= AAE_SLOTS_PER_HANDLE) return; SoundAction& action = getNextOutgoingSoundAction(); action.command = AAE_PITCH; @@ -525,8 +540,8 @@ void AccessibleAudioEngine::setPitch(uintptr_t handle, int slot, float pitch) { action.pitch = pitch; } -void AccessibleAudioEngine::setPitchBehindModifier(uintptr_t handle, int slot, float mod) { - if (slot < 0 || slot >= AAE_SLOTS_PER_HANDLE) +void AccessibleAudioEngine::setPitchBehindModifier(uintptr_t handle, uint8_t slot, float mod) { + if (slot >= AAE_SLOTS_PER_HANDLE) return; SoundAction& action = getNextOutgoingSoundAction(); action.command = AAE_PITCH_BEHIND; @@ -535,8 +550,8 @@ void AccessibleAudioEngine::setPitchBehindModifier(uintptr_t handle, int slot, f action.pitch = mod; } -void AccessibleAudioEngine::setVolume(uintptr_t handle, int slot, float volume) { - if (slot < 0 || slot >= AAE_SLOTS_PER_HANDLE) +void AccessibleAudioEngine::setVolume(uintptr_t handle, uint8_t slot, float volume) { + if (slot >= AAE_SLOTS_PER_HANDLE) return; SoundAction& action = getNextOutgoingSoundAction(); action.command = AAE_VOLUME; @@ -545,8 +560,8 @@ void AccessibleAudioEngine::setVolume(uintptr_t handle, int slot, float volume) action.volume = volume; } -void AccessibleAudioEngine::setPan(uintptr_t handle, int slot, float pan) { - if (slot < 0 || slot >= AAE_SLOTS_PER_HANDLE) +void AccessibleAudioEngine::setPan(uintptr_t handle, uint8_t slot, float pan) { + if (slot >= AAE_SLOTS_PER_HANDLE) return; SoundAction& action = getNextOutgoingSoundAction(); action.command = AAE_PAN; @@ -554,8 +569,8 @@ void AccessibleAudioEngine::setPan(uintptr_t handle, int slot, float pan) { action.slot = slot; action.pan = pan; } -void AccessibleAudioEngine::setFilter(uintptr_t handle, int slot, float cutoff) { - if (slot < 0 || slot >= AAE_SLOTS_PER_HANDLE) +void AccessibleAudioEngine::setFilter(uintptr_t handle, uint8_t slot, float cutoff) { + if (slot >= AAE_SLOTS_PER_HANDLE) return; if (cutoff < 0.0 || cutoff > 1.0) return; @@ -566,8 +581,8 @@ void AccessibleAudioEngine::setFilter(uintptr_t handle, int slot, float cutoff) action.cutoff = cutoff; } -void AccessibleAudioEngine::seekSound(uintptr_t handle, int slot, size_t offset) { - if (slot < 0 || slot >= AAE_SLOTS_PER_HANDLE) +void AccessibleAudioEngine::seekSound(uintptr_t handle, uint8_t slot, size_t offset) { + if (slot >= AAE_SLOTS_PER_HANDLE) return; SoundAction& action = getNextOutgoingSoundAction(); action.handle = handle; @@ -576,9 +591,9 @@ void AccessibleAudioEngine::seekSound(uintptr_t handle, int slot, size_t offset) action.offset = offset; } -void AccessibleAudioEngine::setSoundPosition(uintptr_t handle, int slot, float posX, float posY, float posZ, +void AccessibleAudioEngine::setSoundPosition(uintptr_t handle, uint8_t slot, float posX, float posY, float posZ, float distToPlayer, float maxDistance) { - if (slot < 0 || slot >= AAE_SLOTS_PER_HANDLE) + if (slot >= AAE_SLOTS_PER_HANDLE) return; SoundAction& action = getNextOutgoingSoundAction(); action.command = AAE_POS; diff --git a/soh/soh/Enhancements/accessible-actors/AccessibleAudioEngine.h b/soh/soh/Enhancements/accessible-actors/AccessibleAudioEngine.h index e27454bc9..6bb473ddb 100644 --- a/soh/soh/Enhancements/accessible-actors/AccessibleAudioEngine.h +++ b/soh/soh/Enhancements/accessible-actors/AccessibleAudioEngine.h @@ -18,7 +18,6 @@ struct SoundAction { // address of an object with which the sound is associated is recommended. uint8_t slot; // Allows multiple sounds per handle. The exact number is controlled by AAE_SOUNDS_PER_HANDLE. uint8_t command; // One of the items belonging to AAE_COMMANDS. - bool looping; // If command is AAE_START, specifies whether or not the sound should loop. std::string path; // If command is AAE_START, this is the path to the desired resource. union { float pitch; @@ -126,20 +125,20 @@ class AccessibleAudioEngine { // content). void mix(int16_t* ogBuffer, uint32_t nFrames); // Start playing a sound. - void playSound(uintptr_t handle, int slot, const char* path, bool looping); - void stopSound(uintptr_t handle, int slot); + void playSound(uintptr_t handle, uint8_t slot, const char* path); + void stopSound(uintptr_t handle, uint8_t slot); // Stop all sounds belonging to a handle. void stopAllSounds(uintptr_t handle); - void setPitch(uintptr_t handle, int slot, float pitch); - void setPitchBehindModifier(uintptr_t handle, int slot, float mod); - void setVolume(uintptr_t handle, int slot, float volume); - void setPan(uintptr_t handle, int slot, float pan); + void setPitch(uintptr_t handle, uint8_t slot, float pitch); + void setPitchBehindModifier(uintptr_t handle, uint8_t slot, float mod); + void setVolume(uintptr_t handle, uint8_t slot, float volume); + void setPan(uintptr_t handle, uint8_t slot, float pan); // Set the lowpass filter cutoff. Set to 1.0 for no filtering. - void setFilter(uintptr_t handle, int slot, float cutoff); + void setFilter(uintptr_t handle, uint8_t slot, float cutoff); // Seek the sound to a particular PCM frame. - void seekSound(uintptr_t handle, int slot, size_t offset); - void setSoundPosition(uintptr_t handle, int slot, float posX, float posY, float posZ, float distToPlayer, + void seekSound(uintptr_t handle, uint8_t slot, size_t offset); + void setSoundPosition(uintptr_t handle, uint8_t slot, float posX, float posY, float posZ, float distToPlayer, float maxDistance); // Schedule the preparation of output for delivery. void prepare(); diff --git a/soh/soh/Enhancements/accessible-actors/ActorAccessibility.cpp b/soh/soh/Enhancements/accessible-actors/ActorAccessibility.cpp index cde1078a6..ff4f395e8 100644 --- a/soh/soh/Enhancements/accessible-actors/ActorAccessibility.cpp +++ b/soh/soh/Enhancements/accessible-actors/ActorAccessibility.cpp @@ -75,7 +75,7 @@ class AudioGlossaryData { class ActorAccessibility { public: - int isOn = 0; + bool isOn = false; uint64_t nextActorID = 0; SupportedActors_t supportedActors; TrackedActors_t trackedActors; @@ -87,10 +87,13 @@ class ActorAccessibility { SfxExtractor sfxExtractor; // Maps internal sfx to external (prerendered) resources. std::unordered_map sfxMap; - int extractSfx = 0; + int framesUntilChime = 0; s16 currentScene = -1; s8 currentRoom = -1; - VirtualActorList* currentEverywhere = NULL; + bool currentRoomClear = false; + Vec3f prevPos = { 0, 0, 0 }; + s16 prevYaw = 0; + bool extractSfx = false; VirtualActorList* currentSceneGlobal = NULL; VirtualActorList* currentRoomLocal = NULL; }; @@ -216,11 +219,9 @@ void ActorAccessibility_TrackNewActor(Actor* actor) { aa->trackedActors[actor] = accessibleActor.instanceID; aa->accessibleActorList[accessibleActor.instanceID] = accessibleActor; - AccessibleActor& savedActor = aa->accessibleActorList[accessibleActor.instanceID]; - if (policy->initUserData && !policy->initUserData(&savedActor)) { - ActorAccessibility_RemoveTrackedActor(actor); - - return; // Probably a malloc error preventing user data initialization. + if (policy->initUserData) { + AccessibleActor& savedActor = aa->accessibleActorList[accessibleActor.instanceID]; + policy->initUserData(&savedActor); } } void ActorAccessibility_RemoveTrackedActor(Actor* actor) { @@ -250,11 +251,11 @@ f32 ActorAccessibility_ComputeCurrentVolume(f32 maxDistance, f32 xzDistToPlayer) return ActorAccessibility_DBToLinear(db); } const char* ActorAccessibility_MapSfxToExternalAudio(s16 sfxId); -void ActorAccessibility_PlaySound(void* handle, int slot, s16 sfxId, bool looping) { +void ActorAccessibility_PlaySound(void* handle, int slot, s16 sfxId) { const char* path = ActorAccessibility_MapSfxToExternalAudio(sfxId); if (path == NULL) return; - aa->audioEngine->playSound((uintptr_t)handle, slot, path, looping); + aa->audioEngine->playSound((uintptr_t)handle, slot, path); } void ActorAccessibility_StopSound(void* handle, int slot) { @@ -291,10 +292,10 @@ void ActorAccessibility_ConfigureSoundForActor(AccessibleActor* actor, int slot) ActorAccessibility_SetSoundVolume(actor, slot, actor->policy.volume); actor->managedSoundSlots |= 1 << slot; } -void ActorAccessibility_PlaySoundForActor(AccessibleActor* actor, int slot, s16 sfxId, bool looping) { +void ActorAccessibility_PlaySoundForActor(AccessibleActor* actor, int slot, s16 sfxId) { if (slot < 0 || slot > AAE_SLOTS_PER_HANDLE) return; - ActorAccessibility_PlaySound(actor, slot, sfxId, looping); + ActorAccessibility_PlaySound(actor, slot, sfxId); ActorAccessibility_ConfigureSoundForActor(actor, slot); } void ActorAccessibility_StopSoundForActor(AccessibleActor* actor, int slot) { @@ -351,8 +352,6 @@ void ActorAccessibility_RunAccessibilityForActor(PlayState* play, AccessibleActo } // Send sound parameters to the new audio engine. Eventually remove the old stuff once all actors are carried over. for (int i = 0; i < AAE_SLOTS_PER_HANDLE; i++) { - if (i == 9) - continue; if (actor->managedSoundSlots & (1 << i)) { ActorAccessibility_SetSoundPos(actor, i, &actor->projectedPos, actor->xyzDistToPlayer, actor->policy.distance); @@ -377,16 +376,13 @@ void ActorAccessibility_RunAccessibilityForActor(PlayState* play, AccessibleActo if (player->stateFlags1 & PLAYER_STATE1_FIRST_PERSON && (player->stateFlags1 & PLAYER_STATE1_USING_BOOMERANG || player->stateFlags1 & PLAYER_STATE1_ITEM_IN_HAND)) { auto aimAssistProps = ActorAccessibility_ProvideAimAssistForActor(actor); + if (++actor->aimAssist.framesSinceAimAssist >= actor->aimAssist.frequency) { + actor->aimAssist.framesSinceAimAssist = 0; + ActorAccessibility_PlaySound(actor, 7, actor->policy.aimAssist.sfx); + } ActorAccessibility_SetSoundPitch(actor, 7, aimAssistProps.pitch); ActorAccessibility_SetSoundVolume(actor, 7, aimAssistProps.volume); ActorAccessibility_SetSoundPan(actor, 7, aimAssistProps.pan); - - // The above will have taken care of setting the appropriate frequency and pitch, so we'll take care of the - // audio here based on those results. - if (++actor->aimAssist.framesSinceAimAssist >= actor->aimAssist.frequency) { - actor->aimAssist.framesSinceAimAssist = 0; - ActorAccessibility_PlaySoundForActor(actor, 7, actor->policy.aimAssist.sfx, false); - } } else { // Make sure there's no delay the next time you draw your bow or whatever. actor->aimAssist.framesSinceAimAssist = 32768; @@ -396,16 +392,15 @@ void ActorAccessibility_RunAccessibilityForActor(PlayState* play, AccessibleActo if (actor->policy.callback != nullptr) { actor->policy.callback(actor); } else { - ActorAccessibility_PlaySoundForActor(actor, 0, actor->policy.sound, false); + ActorAccessibility_PlaySoundForActor(actor, 0, actor->policy.sound); } } + void ActorAccessibility_RunAccessibilityForAllActors(PlayState* play) { Player* player = GET_PLAYER(play); if (play->sceneNum != aa->currentScene) { - ActorAccessibility_StopAllVirtualActors(aa->currentEverywhere); ActorAccessibility_StopAllVirtualActors(aa->currentSceneGlobal); ActorAccessibility_StopAllVirtualActors(aa->currentRoomLocal); - aa->currentEverywhere = ActorAccessibility_GetVirtualActorList(EVERYWHERE, 0); aa->currentSceneGlobal = ActorAccessibility_GetVirtualActorList(play->sceneNum, -1); aa->currentScene = play->sceneNum; aa->currentRoomLocal = NULL; @@ -428,19 +423,17 @@ void ActorAccessibility_RunAccessibilityForAllActors(PlayState* play) { } ActorAccessibility_AudioGlossary(play); if (aa->glossary->GlossaryStarted) { - return; } + + ActorAccessibility_GeneralHelper(play); + // Real actors. for (AccessibleActorList_t::iterator i = aa->accessibleActorList.begin(); i != aa->accessibleActorList.end(); i++) ActorAccessibility_RunAccessibilityForActor(play, &i->second); - // Virtual actors in the "everywhere" group. - VAList_t* list = (VAList_t*)aa->currentEverywhere; - for (VAList_t::iterator i = list->begin(); i != list->end(); i++) - ActorAccessibility_RunAccessibilityForActor(play, &(*i)); // Virtual actors for the current room and scene. - list = (VAList_t*)aa->currentRoomLocal; + VAList_t* list = (VAList_t*)aa->currentRoomLocal; for (VAList_t::iterator i = list->begin(); i != list->end(); i++) ActorAccessibility_RunAccessibilityForActor(play, &(*i)); // Scene-global virtual actors. Most of these are automatically generated VAs from polygons, because there's no way @@ -453,6 +446,96 @@ void ActorAccessibility_RunAccessibilityForAllActors(PlayState* play) { ActorAccessibility_PrepareNextAudioFrame(); } +void ActorAccessibility_GeneralHelper(PlayState* play) { + Player* player = GET_PLAYER(play); + if (player == NULL) + return; + + if (aa->currentScene == play->sceneNum && aa->currentRoom != play->roomCtx.curRoom.num) { + ActorAccessibility_AnnounceRoomNumber(play); + aa->currentRoom = play->roomCtx.curRoom.num; + aa->currentRoomClear = Flags_GetClear(play, aa->currentRoom); + } + if (aa->currentScene != play->sceneNum) { + ActorAccessibility_InterpretCurrentScene(play); + aa->currentScene = play->sceneNum; + aa->currentRoom = play->roomCtx.curRoom.num; + aa->currentRoomClear = Flags_GetClear(play, aa->currentRoom); + } + // Report when a room is completed. + if (!aa->currentRoomClear && Flags_GetClear(play, aa->currentRoom)) { + aa->currentRoomClear = Flags_GetClear(play, aa->currentRoom); + ActorAccessibility_AnnounceRoomNumber(play); + } + + if (player->actor.wallPoly && player->actor.speedXZ > 0 && player->yDistToLedge >= 79.0f) { + f32 movedsq = SQ(aa->prevPos.x - player->actor.world.pos.x) + SQ(aa->prevPos.z - player->actor.world.pos.z); + if (movedsq < 0.125) { + ActorAccessibility_PlaySound(nullptr, 3, NA_SE_IT_WALL_HIT_SOFT); + ActorAccessibility_SetSoundVolume(nullptr, 3, 0.5); + } else if (movedsq < 9) { + ActorAccessibility_PlaySound(nullptr, 3, NA_SE_IT_SHIELD_POSTURE); + ActorAccessibility_SetSoundVolume(nullptr, 3, 0.6); + } else { + ActorAccessibility_PlaySound(nullptr, 3, NA_SE_PL_WALK_WALL); + ActorAccessibility_SetSoundVolume(nullptr, 3, std::max(0.3f, 10.0f / movedsq)); + } + } + + bool compassOn = false; + if (aa->prevPos.x == player->actor.world.pos.x && aa->prevPos.z == player->actor.world.pos.z) { + if (aa->prevYaw != player->yaw) { + compassOn = true; + aa->prevYaw = player->yaw; + } + } else { + aa->prevPos = player->actor.world.pos; + } + + if (aa->framesUntilChime > 0) { + aa->framesUntilChime--; + } else { + if (!compassOn) { + OSContPad* trackerButtonsPressed = + std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetControlDeck())->GetPads(); + compassOn = trackerButtonsPressed != nullptr && (trackerButtonsPressed[0].button & BTN_DDOWN) && + (trackerButtonsPressed[0].button & BTN_L); + } + if (compassOn) { + ActorAccessibility_PlaySound(nullptr, 0, NA_SE_EV_SHIP_BELL); + ActorAccessibility_SetSoundPitch(nullptr, 0, 1.5f + Math_CosS(player->yaw) / 2); + ActorAccessibility_SetSoundPan(nullptr, 0, -Math_SinS(player->yaw)); + s16 range = ABS((player->yaw & 0x1FFF) - 0x1000); + aa->framesUntilChime = range < 0x800 ? 10 : range < 0x1000 ? 20 : 30; + } + } + + if (fabs(player->unk_860 - 25) < 24.0 && player->heldItemId == 0) { + ActorAccessibility_PlaySound(nullptr, 1, NA_SE_SY_WARNING_COUNT_N); + } + + if (Player_HoldsHookshot(player) && player->heldActor != NULL && player->actor.scale.y >= 0.0f && + (player->stateFlags1 & PLAYER_STATE1_FIRST_PERSON)) { + CollisionPoly* colPoly; + s32 bgId; + Vec3f firstHit; + f32 hookshotLength = ((player->heldItemAction == PLAYER_IA_HOOKSHOT) ? 380.0f : 770.0f) * + CVarGetFloat(CVAR_CHEAT("HookshotReachMultiplier"), 1.0f); + Vec3f hookshotEnd = player->heldActor->world.pos; + hookshotEnd.x += + Math_SinS(player->heldActor->world.rot.y) * Math_SinS(-player->heldActor->world.rot.x) * hookshotLength; + hookshotEnd.y += Math_SinS(-player->heldActor->world.rot.x) * hookshotLength; + hookshotEnd.z += + Math_CosS(player->heldActor->world.rot.y) * Math_CosS(-player->heldActor->world.rot.x) * hookshotLength; + if (BgCheck_AnyLineTest3(&play->colCtx, &player->heldActor->world.pos, &hookshotEnd, &firstHit, &colPoly, 1, 1, + 1, 1, &bgId)) { + if (SurfaceType_IsHookshotSurface(&play->colCtx, colPoly, bgId)) { + ActorAccessibility_PlaySound(nullptr, 2, NA_SE_IT_HOOKSHOT_STICK_OBJ); + } + } + } +} + void ActorAccessibility_AudioGlossary(PlayState* play) { if (aa->glossary->GlossaryStarted) { freezeActors = true; @@ -548,10 +631,8 @@ AccessibleActor* ActorAccessibility_AddVirtualActor(VirtualActorList* list, VIRT l->push_back(actor); size_t index = l->size() - 1; AccessibleActor* savedActor = &(*l)[l->size() - 1]; - if (policy->initUserData && !policy->initUserData(savedActor)) { - l->pop_back(); - return NULL; // Probably a malloc error preventing user data initialization. - } + if (policy->initUserData) + policy->initUserData(savedActor); return savedActor; } void ActorAccessibility_InterpretCurrentScene(PlayState* play) { @@ -664,7 +745,7 @@ bool ActorAccessibility_InitAudio() { void ActorAccessibility_ShutdownAudio() { if (aa->isOn) { delete aa->audioEngine; - aa->isOn = 0; + aa->isOn = false; } } void ActorAccessibility_MixAccessibleAudioWithGameAudio(int16_t* ogBuffer, uint32_t nFrames) { diff --git a/soh/soh/Enhancements/accessible-actors/ActorAccessibility.h b/soh/soh/Enhancements/accessible-actors/ActorAccessibility.h index 289e64000..b32d4963f 100644 --- a/soh/soh/Enhancements/accessible-actors/ActorAccessibility.h +++ b/soh/soh/Enhancements/accessible-actors/ActorAccessibility.h @@ -6,7 +6,7 @@ struct AccessibleActor; typedef void (*ActorAccessibilityCallback)(AccessibleActor*); // A callback which allows AccessibleActor instances to initialize custom user data (called once per instantiation). -typedef bool (*ActorAccessibilityUserDataInit)(AccessibleActor*); +typedef void (*ActorAccessibilityUserDataInit)(AccessibleActor*); // A callback that can be used to clean up user data when an actor is destroyed. typedef void (*ActorAccessibilityUserDataCleanup)(AccessibleActor*); @@ -108,7 +108,7 @@ void ActorAccessibility_RunAccessibilityForAllActors(PlayState* play); *modifying AAE_SLOTS_PER_HANDLE). sfxId: one of the game's sfx IDs. Note that this plays prerendered sounds which you *must have previously prepared. looping: whether to play the sound just once or on a continuous loop. */ -void ActorAccessibility_PlaySound(void* actor, int slot, s16 sfxId, bool looping); +void ActorAccessibility_PlaySound(void* actor, int slot, s16 sfxId); // Stop a sound. Todo: consider making this a short fade instead of just cutting it off. void ActorAccessibility_StopSound(void* handle, int slot); void ActorAccessibility_StopAllSounds(void* handle); @@ -132,7 +132,7 @@ void ActorAccessibility_SeekSound(void* handle, int slot, size_t offset); * automatically based on the actor's position. * */ -void ActorAccessibility_PlaySoundForActor(AccessibleActor* actor, int slot, s16 sfxId, bool looping); +void ActorAccessibility_PlaySoundForActor(AccessibleActor* actor, int slot, s16 sfxId); void ActorAccessibility_StopSoundForActor(AccessibleActor* actor, int slot); void ActorAccessibility_StopAllSoundsForActor(AccessibleActor* actor); @@ -142,9 +142,8 @@ Vec3s ActorAccessibility_ComputeRelativeAngle(Vec3s* origin, Vec3s* offset); void ActorAccessibility_InitCues(); // Stuff related to lists of virtual actors. typedef enum { - // Similar to the game's actual actor table. Values here start at 10000 just to be extra safe. + // Similar to the game's actual actor table VA_INITIAL = 1000, - VA_PROTOTYPE, // Remove this one once this thing is working. VA_CRAWLSPACE, VA_TERRAIN_CUE, VA_WALL_CUE, @@ -153,9 +152,6 @@ typedef enum { VA_AREA_CHANGE, VA_MARKER, VA_SPIKE, - VA_GENERAL_HELPER, // Room announcements, action icon and other misc help. - VA_AUDIO_COMPASS, // Points north. - VA_STICK_WARNING, // beep when stick is about to burn out. VA_MAX, } VIRTUAL_ACTOR_TABLE; @@ -183,4 +179,5 @@ void ActorAccessibility_HandleSoundExtractionMode(PlayState* play); // This is called by the audio thread when it's ready to try to pull sfx from the game. void ActorAccessibility_DoSoundExtractionStep(); +void ActorAccessibility_GeneralHelper(PlayState* play); void ActorAccessibility_AudioGlossary(PlayState* play); diff --git a/soh/soh/Enhancements/accessible-actors/accessibility_cues.cpp b/soh/soh/Enhancements/accessible-actors/accessibility_cues.cpp index 878f096dc..37546d882 100644 --- a/soh/soh/Enhancements/accessible-actors/accessibility_cues.cpp +++ b/soh/soh/Enhancements/accessible-actors/accessibility_cues.cpp @@ -23,8 +23,8 @@ static Vec3f D_80854798 = { 0.0f, 18.0f, 0.0f }; // From z_player.c. const char* GetLanguageCode(); -enum { - DISCOVERED_NOTHING = 0, +enum DiscoveredTerrain { + DISCOVERED_NOTHING, DISCOVERED_INCLINE, DISCOVERED_DECLINE, DISCOVERED_LEDGE, @@ -46,10 +46,9 @@ class TerrainCueSound { s16 currentSFX; int restFrames; // Used to control how often sounds get played. - bool shouldLoop; // Call to start playback. void play() { - ActorAccessibility_PlaySound(this, 0, currentSFX, shouldLoop); + ActorAccessibility_PlaySound(this, 0, currentSFX); ActorAccessibility_SetSoundPos(this, 0, &terrainProjectedPos, xzDistToPlayer, actor->policy.distance); ActorAccessibility_SetSoundPitch(this, 0, currentPitch); } @@ -80,7 +79,6 @@ class TerrainCueSound { TerrainCueSound(AccessibleActor* actor, Vec3f pos) { this->actor = actor; currentPitch = 1.0; - shouldLoop = false; restFrames = 0; xzDistToPlayer = 0; currentSFX = 0; @@ -104,8 +102,7 @@ class Incline : protected TerrainCueSound { play(); } - virtual ~Incline() { - } + virtual ~Incline() = default; virtual void run() { if (restFrames > 0) { restFrames--; @@ -133,8 +130,7 @@ class Decline : protected TerrainCueSound { play(); } - virtual ~Decline() { - } + virtual ~Decline() = default; virtual void run() { if (restFrames > 0) { restFrames--; @@ -167,49 +163,36 @@ class Ledge : protected TerrainCueSound { switch (type) { case 0: currentSFX = NA_SE_EV_WIND_TRAP; - shouldLoop = 1; break; - case 1: currentSFX = NA_SE_EV_WOOD_BOUND; - shouldLoop = 0; break; case 2: currentSFX = NA_SE_PL_LAND_WATER0; - shouldLoop = 0; break; case 3: currentSFX = NA_SE_SY_WARNING_COUNT_N; - shouldLoop = 0; break; } this->probeRot = probeRot; if (type == 0) { - if (probeRot.y == 0) - currentPitch = 0.4; - else if (probeRot.y < 0) - currentPitch = 0.2; - else - currentPitch = 0.8; + currentPitch = probeRot.y == 0 ? 0.4 : probeRot.y < 0 ? 0.2 : 0.8; } play(); } - virtual ~Ledge() { - } + virtual ~Ledge() = default; s8 type() { return savedType; } void run() { - if (savedType == 0) - return; // Downward ledges play a looping sound and do not need ongoing maintenance. if (restFrames == 0) { play(); restFrames = 10; - return; + } else { + restFrames--; } - restFrames--; } }; class Platform : protected TerrainCueSound { @@ -218,10 +201,8 @@ class Platform : protected TerrainCueSound { currentPitch = 2.0; // actor->policy.volume = 1.5; currentSFX = NA_SE_IT_SHIELD_REFLECT_SW; - shouldLoop = false; - } - virtual ~Platform() { } + virtual ~Platform() = default; void setActor(AccessibleActor* actor) { this->actor = actor; } @@ -232,9 +213,9 @@ class Platform : protected TerrainCueSound { if (restFrames == 0) { play(); restFrames = 10; - return; + } else { + restFrames--; } - restFrames--; } }; @@ -258,8 +239,7 @@ class Wall : protected TerrainCueSound { play(); } - virtual ~Wall() { - } + virtual ~Wall() = default; void run() { frames++; @@ -286,8 +266,7 @@ class Spike : protected TerrainCueSound { currentSFX = NA_SE_IT_SWORD_PICKOUT; play(); } - virtual ~Spike() { - } + virtual ~Spike() = default; void run() { if (restFrames == 0) { play(); @@ -304,15 +283,14 @@ class Water : protected TerrainCueSound { currentSFX = NA_SE_PL_LAND_WATER0; // NA_SE_EN_DAIOCTA_LAND_WATER; // change? play(); } - virtual ~Water() { - } + virtual ~Water() = default; void run() { if (restFrames == 0) { play(); restFrames = 10; - return; + } else { + restFrames--; } - restFrames--; } }; @@ -326,16 +304,15 @@ class Ground : protected TerrainCueSound { this->pitchModifier = 0.0; play(); } - virtual ~Ground() { - } + virtual ~Ground() = default; void run() { if (restFrames == 0) { play(); restFrames = 10; - return; + } else { + ActorAccessibility_SetSoundPitch(this, 0, 1.0 + (2 * pitchModifier)); + restFrames--; } - ActorAccessibility_SetSoundPitch(this, 0, 1.0 + (2 * pitchModifier)); - restFrames--; } void setPitchModifier(float modifier) { pitchModifier = modifier; @@ -349,19 +326,18 @@ class Lava : protected TerrainCueSound { currentSFX = NA_SE_SY_WARNING_COUNT_N; // change? play(); } - virtual ~Lava() { - } + virtual ~Lava() = default; void run() { if (restFrames == 0) { play(); restFrames = 10; - return; + } else { + restFrames--; } - restFrames--; } }; -class TerrainCueDirection { +class TerrainCueDirection final { AccessibleActor* actor; int startingBodyPart; // Decides where the probe starts from. Probes going out to the left or right of the player // start from the shoulders. @@ -375,7 +351,7 @@ class TerrainCueDirection { f32 probeSpeed; // Approximate for now. Vec3f velocity; Vec3f expectedVelocity; - int terrainDiscovered = DISCOVERED_NOTHING; + DiscoveredTerrain terrainDiscovered = DISCOVERED_NOTHING; CollisionPoly* floorPoly; CollisionPoly* wallPoly; s32 wallBgId; @@ -401,6 +377,7 @@ class TerrainCueDirection { Platform platform; TerrainCueSound* currentSound; + // Apply an offset b to a Vec3f a. Vec3f applyVec3fOffset(Vec3f& a, Vec3f& b) { Vec3f c; @@ -742,7 +719,8 @@ class TerrainCueDirection { public: // Initialize a TerrainCueDirection based on a relative angle and position offset. - void init(AccessibleActor* actor, Vec3s rot, int startingBodyPart = PLAYER_BODYPART_MAX) { + TerrainCueDirection(AccessibleActor* actor, Vec3s rot, int startingBodyPart = PLAYER_BODYPART_MAX) + : platform(actor, { 0, 0, 0 }) { this->actor = actor; this->relRot = rot; this->rot = { 0, 0, 0 }; @@ -750,12 +728,44 @@ class TerrainCueDirection { terrainDiscovered = DISCOVERED_NOTHING; currentSound = NULL; - new (&platform) Platform(actor, { 0.0, 0.0, 0.0 }); disabled = false; trackingMode = false; trackingModeStarted = false; } + + ~TerrainCueDirection() { + switch (terrainDiscovered) { + case DISCOVERED_NOTHING: + break; + case DISCOVERED_INCLINE: + this->incline.~Incline(); + break; + case DISCOVERED_DECLINE: + this->decline.~Decline(); + break; + case DISCOVERED_LEDGE: + this->ledge.~Ledge(); + break; + case DISCOVERED_WALL: + this->wall.~Wall(); + break; + case DISCOVERED_SPIKE: + this->spike.~Spike(); + break; + case DISCOVERED_WATER: + this->water.~Water(); + break; + case DISCOVERED_GROUND: + this->ground.~Ground(); + break; + case DISCOVERED_LAVA: + this->lava.~Lava(); + break; + } + this->platform.~Platform(); + } + // Move a probe to its next point along a line, ensuring that it remains on the floor. Returns false if the move // would put the probe out of bounds. Does not take walls into account. bool move(s8 gravity = true) { @@ -1121,12 +1131,7 @@ class TerrainCueDirection { } } destroyCurrentSound(); - break; /*else { - if (checkHeight < 200) { - discoverLedge(pos, true); - break; - } - }*/ // not needed? + break; } if (moveMethod != 2 && checkPerpendicularWall(pos, ogRot)) { discoverWall(pos); @@ -1134,10 +1139,7 @@ class TerrainCueDirection { } discoverLedge(pos, false); break; - - } - - else if (checkForLava(player->actor.world.pos)) { + } else if (checkForLava(player->actor.world.pos)) { if (!move()) { destroyCurrentSound(); break; // Probe is out of bounds. @@ -1146,12 +1148,9 @@ class TerrainCueDirection { discoverGround(pos); break; } - } - // link is on land else { - if (!move()) { destroyCurrentSound(); break; // Probe is out of bounds. @@ -1348,19 +1347,17 @@ typedef struct { } TerrainCueState; // Callback for initialization of terrain cue state. -bool ActorAccessibility_InitTerrainCueState(AccessibleActor* actor) { - TerrainCueState* state = (TerrainCueState*)malloc(sizeof(TerrainCueState)); - if (state == NULL) - return false; - state->directions[0].init(actor, { 0, 0, 0 }); - state->directions[1].init(actor, { 0, 16384, 0 }); - state->directions[2].init(actor, { 0, -16384, 0 }); +void ActorAccessibility_InitTerrainCueState(AccessibleActor* actor) { + TerrainCueState* state = new TerrainCueState{ { + { actor, { 0, 0, 0 } }, + { actor, { 0, 16384, 0 } }, + { actor, { 0, -16384, 0 } }, + } }; actor->userData = state; - return true; } void ActorAccessibility_CleanupTerrainCueState(AccessibleActor* actor) { - free(actor->userData); + delete (TerrainCueState*)actor->userData; actor->userData = NULL; } // Computes a relative angle based on Link's (or some other actor's) current angle.