diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index 00868a91d99..d929b5ea3a8 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -279,21 +279,22 @@ namespace Ship { WmApi->set_keyboard_callbacks(Window::KeyDown, Window::KeyUp, Window::AllKeysUp); } - void task1(const char textToRead[]) + void task1(const std::string & textToRead) { const int w = 512; int* wp = const_cast (&w); - *wp = strlen(textToRead); + *wp = strlen(textToRead.c_str()); wchar_t wtext[w]; - mbstowcs(wtext, textToRead, strlen(textToRead) + 1); + mbstowcs(wtext, textToRead.c_str(), strlen(textToRead.c_str()) + 1); pVoice->Speak(wtext, SPF_IS_XML | SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL); } void Window::ReadText(const char textToRead[]) { - std::thread t1(task1, textToRead); + std::string textCopy(textToRead); + std::thread t1(task1, textCopy); t1.detach(); } diff --git a/soh/include/z64collision_check.h b/soh/include/z64collision_check.h index 4dad0acc7dd..426b05f05b8 100644 --- a/soh/include/z64collision_check.h +++ b/soh/include/z64collision_check.h @@ -269,7 +269,8 @@ typedef enum { /* 4 */ ELEMTYPE_UNK4, /* 5 */ ELEMTYPE_UNK5, /* 6 */ ELEMTYPE_UNK6, - /* 7 */ ELEMTYPE_UNK7 + /* 7 */ ELEMTYPE_UNK7, + /* 8 */ ELEMTYPE_SENSING } ElementType; #define AT_NONE 0 // No flags set. Cannot have AT collisions when set as AT diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index cc06ff659af..9a1b9c1c3db 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -25,6 +25,9 @@ void BootCommands_Init() CVar_RegisterS32("gDebugEnabled", 0); CVar_RegisterS32("gPauseLiveLink", 0); CVar_RegisterS32("gDPadLook", 0); + CVar_RegisterS32("gAccessibleInteraction", 0); + CVar_RegisterS32("gMoreTargets", 0); + CVar_RegisterS32("gAimAudioCues", 0); } //void BootCommands_ParseBootArgs(char* str) diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 976ec0386cd..5ccaa2dffa8 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -517,6 +517,7 @@ void func_8002C7BC(TargetContext* targetCtx, Player* player, Actor* actorArg, Gl targetCtx->activeCategory = actorCategory; targetCtx->unk_40 = 1.0f; + /* if (CVar_GetS32("gBlindMode", 0)) { u16 targetSound; @@ -554,6 +555,7 @@ void func_8002C7BC(TargetContext* targetCtx, Player* player, Actor* actorArg, Gl Audio_PlaySoundGeneral(targetSound, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); } } + */ } if (unkActor == NULL) { @@ -1787,8 +1789,33 @@ u32 func_8002F090(Actor* actor, f32 arg1) { return arg1 < D_80115FF8[actor->targetMode].rangeSq; } +s32 Actor_IsTargetable(Actor* actor, Player* player) { + s32 targetMode = CVar_GetS32("gMoreTargets", 0); + + if ((actor->update == NULL) || ((Player*)actor == player)) { + return false; + } + + if (targetMode == 99) { + return true; + } else if (targetMode == 2) { + return CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_0) || + actor->category == ACTORCAT_CHEST || + actor->category == ACTORCAT_SWITCH || + actor->id == ACTOR_EN_SW || actor->id == ACTOR_BOSS_GANON || + actor->id == ACTOR_OBJ_HSBLOCK || actor->id == ACTOR_OBJ_SYOKUDAI; + } else if (targetMode == 1) { + return CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_0) || + actor->category == ACTORCAT_CHEST || + actor->category == ACTORCAT_SWITCH; + } else { + //original/default + return CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_0); + } +} + s32 func_8002F0C8(Actor* actor, Player* player, s32 flag) { - if ((actor->update == NULL) || !(actor->flags & ACTOR_FLAG_0)) { + if (!Actor_IsTargetable(actor, player)) { return true; } @@ -3225,7 +3252,7 @@ void func_800328D4(GlobalContext* globalCtx, ActorContext* actorCtx, Player* pla sp84 = player->unk_664; while (actor != NULL) { - if ((actor->update != NULL) && ((Player*)actor != player) && CHECK_FLAG_ALL(actor->flags, ACTOR_FLAG_0)) { + if (Actor_IsTargetable(actor, player)) { // This block below is for determining the closest actor to player in determining the volume // used while playing enemy bgm music diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 7302f9b2185..9c5f480b8f5 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -1408,6 +1408,66 @@ s32 Camera_Noop(Camera* camera) { return true; } +s32 Camera_Blind(Camera* camera) { + Normal1* norm1 = (Normal1*)camera->paramData; + + f32 playerHeight = Player_GetHeight(camera->player); + f32 sp94; + CamColChk bgChk; + + sCameraInterfaceFlags = norm1->interfaceFlags; + + if (RELOAD_PARAMS) { + VecSph eyeAdjustment1; + Vec3f oldCamRot; + oldCamRot.x = camera->player->actor.world.pos.x; + oldCamRot.y = camera->player->actor.world.pos.y + Player_GetHeight(camera->player); + oldCamRot.z = camera->player->actor.world.pos.z; + OLib_Vec3fDiffToVecSphGeo(&eyeAdjustment1, &oldCamRot, &camera->eye); + OLib_Vec3fDiffToVecSphGeo(&eyeAdjustment1, &oldCamRot, &camera->eyeNext); + + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + f32 yNormal = (1.0f + PCT(R_CAM_YOFFSET_NORM) - PCT(R_CAM_YOFFSET_NORM) * (68.0f / playerHeight)); + sp94 = yNormal * PCT(playerHeight); + + norm1->yOffset = NEXTSETTING * sp94; + norm1->distMin = NEXTSETTING * sp94; + norm1->distMax = NEXTSETTING * sp94; + norm1->pitchTarget = DEGF_TO_BINANG(NEXTSETTING); + norm1->unk_0C = NEXTSETTING; + norm1->unk_10 = NEXTSETTING; + norm1->unk_14 = NEXTPCT; + norm1->fovTarget = NEXTSETTING; + norm1->atLERPScaleMax = NEXTPCT; + norm1->interfaceFlags = NEXTSETTING; + } + + if (R_RELOAD_CAM_PARAMS) { + Camera_CopyPREGToModeValues(camera); + } + + VecSph eyeAdjustment; + + camera->animState = 1; + + camera->at.x = camera->player->actor.world.pos.x; + camera->at.y = camera->player->actor.world.pos.y + Player_GetHeight(camera->player); + camera->at.z = camera->player->actor.world.pos.z; + + OLib_Vec3fDiffToVecSphGeo(&eyeAdjustment, &camera->at, &camera->eye); + OLib_Vec3fDiffToVecSphGeo(&eyeAdjustment, &camera->at, &camera->eyeNext); + + camera->dist = eyeAdjustment.r = 250.0f; + + eyeAdjustment.yaw = 0; + eyeAdjustment.pitch = 9000; + + Camera_Vec3fVecSphGeoAdd(&camera->eye, &camera->at, &eyeAdjustment); + Camera_Vec3fVecSphGeoAdd(&camera->eyeNext, &camera->at, &eyeAdjustment); + + return 1; +} + s32 Camera_Normal1(Camera* camera) { Vec3f* eye = &camera->eye; Vec3f* at = &camera->at; @@ -1559,16 +1619,18 @@ s32 Camera_Normal1(Camera* camera) { if (anim->startSwingTimer <= 0) { eyeAdjustment.pitch = atEyeNextGeo.pitch; - eyeAdjustment.yaw = + eyeAdjustment.yaw = CVar_GetS32("gBlindMode", 0) != 0 ? atEyeNextGeo.yaw + : Camera_LERPCeilS(anim->swingYawTarget, atEyeNextGeo.yaw, 1.0f / camera->yawUpdateRateInv, 0xA); } else if (anim->swing.unk_18 != 0) { - eyeAdjustment.yaw = + eyeAdjustment.yaw = CVar_GetS32("gBlindMode", 0) != 0 ? atEyeNextGeo.yaw + : Camera_LERPCeilS(anim->swing.unk_16, atEyeNextGeo.yaw, 1.0f / camera->yawUpdateRateInv, 0xA); eyeAdjustment.pitch = Camera_LERPCeilS(anim->swing.unk_14, atEyeNextGeo.pitch, 1.0f / camera->yawUpdateRateInv, 0xA); } else { // rotate yaw to follow player. - eyeAdjustment.yaw = + eyeAdjustment.yaw = Camera_CalcDefaultYaw(camera, atEyeNextGeo.yaw, camera->playerPosRot.rot.y, norm1->unk_14, sp94); eyeAdjustment.pitch = Camera_CalcDefaultPitch(camera, atEyeNextGeo.pitch, norm1->pitchTarget, anim->slopePitchAdj); diff --git a/soh/src/code/z_collision_check.c b/soh/src/code/z_collision_check.c index 3170eb87a56..5c8f4e17a8b 100644 --- a/soh/src/code/z_collision_check.c +++ b/soh/src/code/z_collision_check.c @@ -1702,23 +1702,25 @@ s32 CollisionCheck_SetATvsAC(GlobalContext* globalCtx, Collider* at, ColliderInf at->actor->colChkInfo.atHitEffect = acInfo->bumper.effect; } } - ac->acFlags |= AC_HIT; - ac->ac = at->actor; - acInfo->acHit = at; - acInfo->acHitInfo = atInfo; - acInfo->bumperFlags |= BUMP_HIT; - if (ac->actor != NULL) { - ac->actor->colChkInfo.acHitEffect = atInfo->toucher.effect; - } - acInfo->bumper.hitPos.x = hitPos->x; - acInfo->bumper.hitPos.y = hitPos->y; - acInfo->bumper.hitPos.z = hitPos->z; - if (!(atInfo->toucherFlags & TOUCH_AT_HITMARK) && ac->colType != COLTYPE_METAL && ac->colType != COLTYPE_WOOD && - ac->colType != COLTYPE_HARD) { - acInfo->bumperFlags |= BUMP_DRAW_HITMARK; - } else { - CollisionCheck_HitEffects(globalCtx, at, atInfo, ac, acInfo, hitPos); - atInfo->toucherFlags |= TOUCH_DREW_HITMARK; + if (atInfo->elemType != ELEMTYPE_SENSING) { + ac->acFlags |= AC_HIT; + ac->ac = at->actor; + acInfo->acHit = at; + acInfo->acHitInfo = atInfo; + acInfo->bumperFlags |= BUMP_HIT; + if (ac->actor != NULL) { + ac->actor->colChkInfo.acHitEffect = atInfo->toucher.effect; + } + acInfo->bumper.hitPos.x = hitPos->x; + acInfo->bumper.hitPos.y = hitPos->y; + acInfo->bumper.hitPos.z = hitPos->z; + if (!(atInfo->toucherFlags & TOUCH_AT_HITMARK) && ac->colType != COLTYPE_METAL && ac->colType != COLTYPE_WOOD && + ac->colType != COLTYPE_HARD) { + acInfo->bumperFlags |= BUMP_DRAW_HITMARK; + } else { + CollisionCheck_HitEffects(globalCtx, at, atInfo, ac, acInfo, hitPos); + atInfo->toucherFlags |= TOUCH_DREW_HITMARK; + } } return 1; } diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index f932d3406eb..2439a8edd0b 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -118,6 +118,11 @@ s16 sOcarinaNoteCEnvR; s16 sOcarinaNoteCEnvB; s16 sOcarinaNoteCEnvG; +static u8 sTtsHasNewMessage; +static u8 sTtsHasMessage; +static s8 sTtsCurrentChoice; +static u8 sTtsMessageBuf[256]; + void Message_ResetOcarinaNoteState(void) { R_OCARINA_NOTES_YPOS(0) = 189; R_OCARINA_NOTES_YPOS(1) = 184; @@ -3004,6 +3009,108 @@ void Message_Draw(GlobalContext* globalCtx) { CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_message_PAL.c", 3582); } +void Message_TTS_Decode(u8* srcBuf, u8* dstBuf, u32 srcOffset, u32 size) { + u32 dstIdx = 0; + + for (u32 i = 0; i < size; i++) { + u8 currChar = srcBuf[i + srcOffset]; + + if (currChar < ' ') { + switch (currChar) { + case MESSAGE_NEWLINE: + dstBuf[dstIdx++] = ' '; + break; + case MESSAGE_COLOR: + case MESSAGE_SHIFT: + case MESSAGE_TEXT_SPEED: + case MESSAGE_BOX_BREAK_DELAYED: + case MESSAGE_FADE: + case MESSAGE_ITEM_ICON: + i++; + break; + case MESSAGE_FADE2: + case MESSAGE_SFX: + case MESSAGE_TEXTID: + i += 2; + break; + default: + break; + } + } else { + dstBuf[dstIdx++] = currChar; + } + } + + dstBuf[dstIdx] = 0; +} + +void Message_TTS_Update(GlobalContext* globalCtx) { + MessageContext* msgCtx = &globalCtx->msgCtx; + + if (msgCtx->msgMode == MSGMODE_TEXT_NEXT_MSG || msgCtx->msgMode == MSGMODE_DISPLAY_SONG_PLAYED_TEXT_BEGIN || + (msgCtx->msgMode == MSGMODE_TEXT_CONTINUING && msgCtx->stateTimer == 1)) { + sTtsHasNewMessage = 1; + } else if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING || msgCtx->msgMode == MSGMODE_OCARINA_STARTING || + msgCtx->msgMode == MSGMODE_OCARINA_PLAYING || msgCtx->msgMode == MSGMODE_TEXT_AWAIT_NEXT || + msgCtx->msgMode == MSGMODE_TEXT_DONE || msgCtx->msgMode == MSGMODE_DISPLAY_SONG_PLAYED_TEXT || + msgCtx->msgMode == MSGMODE_TEXT_DELAYED_BREAK) { + if (sTtsHasNewMessage == 1) { + sTtsHasNewMessage = 0; + sTtsHasMessage = 1; + sTtsCurrentChoice = 0; + + u32 size = msgCtx->decodedTextLen; + Message_TTS_Decode(msgCtx->msgBufDecoded, sTtsMessageBuf, 0, size); + OTRTextToSpeechCallback(sTtsMessageBuf); + } else if (msgCtx->msgMode == MSGMODE_TEXT_DONE && msgCtx->choiceNum > 0 && + msgCtx->choiceIndex != sTtsCurrentChoice) { + sTtsCurrentChoice = msgCtx->choiceIndex; + u32 startOffset = 0; + u32 endOffset = 0; + while (startOffset < msgCtx->decodedTextLen) { + if (msgCtx->msgBufDecoded[startOffset] == MESSAGE_TWO_CHOICE || + msgCtx->msgBufDecoded[startOffset] == MESSAGE_THREE_CHOICE) { + startOffset++; + break; + } + startOffset++; + } + if (startOffset < msgCtx->decodedTextLen) { + u8 i = msgCtx->choiceIndex; + while (i-- > 0) { + while (startOffset < msgCtx->decodedTextLen) { + if (msgCtx->msgBufDecoded[startOffset] == MESSAGE_NEWLINE) { + startOffset++; + break; + } + startOffset++; + } + } + endOffset = startOffset; + while (endOffset < msgCtx->decodedTextLen) { + if (msgCtx->msgBufDecoded[endOffset] == MESSAGE_NEWLINE) { + break; + } + endOffset++; + } + + if (startOffset < msgCtx->decodedTextLen && startOffset != endOffset) { + u32 size = endOffset - startOffset; + Message_TTS_Decode(msgCtx->msgBufDecoded, sTtsMessageBuf, startOffset, size); + OTRTextToSpeechCallback(sTtsMessageBuf); + } + } + } + } else if (sTtsHasMessage == 1) { + sTtsHasMessage = 0; + sTtsHasNewMessage = 0; + if (msgCtx->decodedTextLen < 3 || (msgCtx->msgBufDecoded[msgCtx->decodedTextLen - 2] != MESSAGE_FADE && + msgCtx->msgBufDecoded[msgCtx->decodedTextLen - 3] != MESSAGE_FADE2)) { + OTRTextToSpeechCallback(""); // cancel current speech (except for faded out messages) + } + } +} + void Message_Update(GlobalContext* globalCtx) { static s16 sTextboxXPositions[] = { 34, 34, 34, 34, 34, 34, @@ -3067,6 +3174,10 @@ void Message_Update(GlobalContext* globalCtx) { return; } + if (CVar_GetS32("gMessageTTS", 0) != 0) { + Message_TTS_Update(globalCtx); + } + bool isB_Held = CVar_GetS32("gFastText", 0) != 0 ? CHECK_BTN_ALL(input->cur.button, BTN_B) && !sTextboxSkipped : CHECK_BTN_ALL(input->press.button, BTN_B); diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index e15cc81eba1..1b6413408d7 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -1260,6 +1260,193 @@ Vec3f D_801261E0[] = { { 200.0f, 200.0f, 0.0f }, }; + +#define AIMCUE_COLLIDER_COUNT 5 +static ColliderQuad sAimCueCollider[AIMCUE_COLLIDER_COUNT]; +static s32 sAimSurfaceHookshotable; +static s32 sAimLastHookshotableState; + +static ColliderQuadInit sSensingColliderInit = { + { + COLTYPE_NONE, + AT_ON | AT_TYPE_PLAYER, + AC_NONE, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_2 | OC2_TYPE_1, + COLSHAPE_QUAD, + }, + { + ELEMTYPE_SENSING, + { 0xFFFFFFFF, 0x00, 0x00 }, + { 0xFFFFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_NEAREST | TOUCH_SFX_NONE, + BUMP_NONE, + OCELEM_NONE, + }, + { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } }, +}; + +void Player_InitAimCueCollision(Player* this, GlobalContext* globalCtx) { + for (int i = 0; i < AIMCUE_COLLIDER_COUNT; i++) { + Collider_InitQuad(globalCtx, &sAimCueCollider[i]); + Collider_SetQuad(globalCtx, &sAimCueCollider[i], NULL, &sSensingColliderInit); + } +} + +void Player_UpdateAimCue(Player* this, GlobalContext* globalCtx) { + Actor* hitActor = NULL; + + for (int i = 0; i < AIMCUE_COLLIDER_COUNT; i++) { + if (sAimCueCollider[i].base.atFlags & AT_HIT) { + sAimCueCollider[i].base.atFlags &= ~AC_HIT; + + if (hitActor == NULL && sAimCueCollider[i].base.at != NULL) { + hitActor = sAimCueCollider[i].base.at; + } else { + continue; + } + + if (i != 0 && (globalCtx->gameplayFrames % 1) != 0) { + continue; + } + + u16 soundEffect = (i == 0) ? NA_SE_SY_HITPOINT_ALARM : NA_SE_SY_FSEL_CURSOR; + + if (hitActor->category == ACTORCAT_ENEMY || hitActor->category == ACTORCAT_BOSS) { + Audio_PlaySoundGeneral(soundEffect, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } else if (hitActor->category == ACTORCAT_SWITCH) { + Audio_PlaySoundGeneral(soundEffect, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } else if (hitActor->category == ACTORCAT_NPC) { + Audio_PlaySoundGeneral(soundEffect, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } else if (hitActor->category == ACTORCAT_PROP && + (hitActor->id == ACTOR_EN_DNT_NOMAL && hitActor->params == 0) || + hitActor->id == ACTOR_EN_G_SWITCH) { + // lost woods slingshot target, shooting gallery rupees + Audio_PlaySoundGeneral(soundEffect, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } + } + } + + if (sAimSurfaceHookshotable != sAimLastHookshotableState) { + if (sAimSurfaceHookshotable) { + Audio_PlaySoundGeneral(NA_SE_SY_LOCK_ON_HUMAN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } else { + Audio_PlaySoundGeneral(NA_SE_SY_LOCK_OFF, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } + sAimLastHookshotableState = sAimSurfaceHookshotable; + } +} + +void Player_ComputeAimCue(Player* this, GlobalContext* globalCtx, s32 limbIndex) { + if (this->heldItemId == 0) { + return; + } + + bool isHoldingHookshotType = Player_HoldsHookshot(this); + + if (!isHoldingHookshotType && limbIndex != PLAYER_LIMB_L_HAND || + isHoldingHookshotType && limbIndex != PLAYER_LIMB_R_HAND) { + return; + } + + sAimSurfaceHookshotable = 0; + + bool isCharged = (this->stateFlags1 & 0x200) && (this->unk_834 <= 10) && (this->unk_860 >= 0); + bool isAiming = !!func_8002DD78(this); + if (!isAiming || !(isCharged || isHoldingHookshotType)) { + return; + } + + CollisionPoly* polyResult; + s32 bgId; + + Matrix_Push(); + + f32 distance; + Vec3f vecCenter; + Vec3f vecCenterFar; + Vec3f vecA; + Vec3f vecB; + Vec3f vecC; + Vec3f vecD; + Vec3f vecResult; + Vec3f vecZero = { 0.0f, 0.0f, 0.0f }; + Vec3f vecLeft = { 0.0f, 50.0f, 0.0f }; + Vec3f vecRight = { 0.0f, -50.0f, 0.0f }; + + if (isHoldingHookshotType) { + if (this->heldItemActionParam == PLAYER_AP_HOOKSHOT) { + distance = 38600.0f; + } else { + distance = 77600.0f; + } + Matrix_Translate(0.0f, 150.0f, -100.0f, MTXMODE_APPLY); + } else { + distance = 200000.0f; + Matrix_Translate(-550.0f, -50.0f, -100.0f, MTXMODE_APPLY); + } + + Matrix_MultVec3f(&vecZero, &vecCenter); + vecZero.z = distance; + Matrix_MultVec3f(&vecZero, &vecCenterFar); + + if (BgCheck_AnyLineTest3(&globalCtx->colCtx, &vecCenter, &vecCenterFar, &vecResult, &polyResult, 1, 1, 1, 1, + &bgId)) { + sAimSurfaceHookshotable = + isHoldingHookshotType && SurfaceType_IsHookshotSurface(&globalCtx->colCtx, polyResult, bgId); + distance *= Math_Vec3f_DistXYZ(&vecCenter, &vecResult) / Math_Vec3f_DistXYZ(&vecCenter, &vecCenterFar); + } + + if (!isCharged) { + Matrix_Pop(); + return; + } + + Matrix_MultVec3f(&vecLeft, &vecA); + Matrix_MultVec3f(&vecRight, &vecB); + + vecLeft.z = distance; + vecRight.z = distance; + + Matrix_MultVec3f(&vecLeft, &vecC); + Matrix_MultVec3f(&vecRight, &vecD); + + Collider_SetQuadVertices(&sAimCueCollider[0], &vecA, &vecB, &vecC, &vecD); + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &sAimCueCollider[0].base); + + Matrix_Scale(500.0f, 500.0f, 1.0f, MTXMODE_APPLY); + + f32 rotateOffset = (globalCtx->gameplayFrames % 4) * M_PI / 16; + Matrix_RotateZ(rotateOffset, MTXMODE_APPLY); + + for (int i = 1; i < AIMCUE_COLLIDER_COUNT; i++) { + if (i > 1) { + Matrix_RotateZ(M_PI / 4, MTXMODE_APPLY); + } + + vecLeft.z = 0; + vecLeft.y = 0.5; + vecRight.z = 0; + vecRight.y = -0.5; + + Matrix_MultVec3f(&vecLeft, &vecA); + Matrix_MultVec3f(&vecRight, &vecB); + + vecLeft.z = distance * 1.2; + vecLeft.y = sqrtf(distance) * 0.2f; + vecRight.z = distance * 1.2; + vecRight.y = sqrtf(distance) * -0.2f; + + Matrix_MultVec3f(&vecLeft, &vecC); + Matrix_MultVec3f(&vecRight, &vecD); + + Collider_SetQuadVertices(&sAimCueCollider[i], &vecA, &vecB, &vecC, &vecD); + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &sAimCueCollider[i].base); + } + + Matrix_Pop(); +} + void func_80090D20(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { Player* this = (Player*)thisx; @@ -1413,9 +1600,11 @@ void func_80090D20(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* heldActor->shape.rot = heldActor->world.rot; if (func_8002DD78(this) != 0) { + Matrix_Push(); Matrix_Translate(500.0f, 300.0f, 0.0f, MTXMODE_APPLY); Player_DrawHookshotReticle( globalCtx, this, (this->heldItemActionParam == PLAYER_AP_HOOKSHOT) ? 38600.0f : 77600.0f); + Matrix_Pop(); } } } @@ -1452,6 +1641,10 @@ void func_80090D20(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* Actor_SetFeetPos(&this->actor, limbIndex, PLAYER_LIMB_L_FOOT, vec, PLAYER_LIMB_R_FOOT, vec); } } + + if (CVar_GetS32("gAimAudioCues", 0)) { + Player_ComputeAimCue(this, globalCtx, limbIndex); + } } u32 func_80091738(GlobalContext* globalCtx, u8* segment, SkelAnime* skelAnime) { diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index 7d8886953d6..22022653eeb 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -420,10 +420,16 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) { osSyncPrintf("Actor_Environment_Tbox_On() %d\n", this->dyna.actor.params & 0x1F); Flags_SetTreasure(globalCtx, this->dyna.actor.params & 0x1F); } else { - player = GET_PLAYER(globalCtx); - func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos); - if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f && - Player_IsFacingActor(&this->dyna.actor, 0x3000, globalCtx)) { + bool isPlayerInFrontOfActor; + if (CVar_GetS32("gAccessibleInteraction", 0)) { + isPlayerInFrontOfActor = true; + } else { + player = GET_PLAYER(globalCtx); + func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos); + isPlayerInFrontOfActor = sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f; + } + + if (isPlayerInFrontOfActor && Player_IsFacingActor(&this->dyna.actor, 0x3000, globalCtx)) { func_8002F554(&this->dyna.actor, globalCtx, 0 - (this->dyna.actor.params >> 5 & 0x7F)); } if (Flags_GetTreasure(globalCtx, this->dyna.actor.params & 0x1F)) { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index b5eca150717..c8d9e9f33e2 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -9363,6 +9363,10 @@ void Player_InitCommon(Player* this, GlobalContext* globalCtx, FlexSkeletonHeade Collider_SetQuad(globalCtx, &this->swordQuads[1], &this->actor, &D_80854650); Collider_InitQuad(globalCtx, &this->shieldQuad); Collider_SetQuad(globalCtx, &this->shieldQuad, &this->actor, &D_808546A0); + + if (CVar_GetS32("gAimAudioCues", 0)) { + Player_InitAimCueCollision(this, globalCtx); + } } static void (*D_80854738[])(GlobalContext* globalCtx, Player* this) = { @@ -10723,6 +10727,10 @@ void Player_UpdateCommon(Player* this, GlobalContext* globalCtx, Input* input) { Collider_ResetQuadAC(globalCtx, &this->shieldQuad.base); Collider_ResetQuadAT(globalCtx, &this->shieldQuad.base); + + if (CVar_GetS32("gAimAudioCues", 0)) { + Player_UpdateAimCue(this, globalCtx); + } } static Vec3f D_80854838 = { 0.0f, 0.0f, -30.0f };