diff --git a/soh/soh/Enhancements/TimeSavers/FasterHeavyBlockLift.cpp b/soh/soh/Enhancements/TimeSavers/FasterHeavyBlockLift.cpp new file mode 100644 index 000000000..ca73877c6 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/FasterHeavyBlockLift.cpp @@ -0,0 +1,58 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" +#include "spdlog/spdlog.h" + +extern "C" { + #include "z64save.h" + #include "macros.h" + #include "variables.h" + #include "functions.h" + extern PlayState* gPlayState; + extern SaveContext gSaveContext; +} + +/** + * This primarily handles speeding up the heavy block lifts (OGC and in the Fire Trial) but also handles skipping + * the one point cutscene since the two options are so similar in what they do. + */ +void FasterHeavyBlockLift_Register() { + REGISTER_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, { + Actor* actor = static_cast(opt); + + if ( + actor->id == ACTOR_BG_HEAVY_BLOCK && + (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) + ) { + *should = false; + } + }); + + REGISTER_VB_SHOULD(VB_FREEZE_LINK_FOR_BLOCK_THROW, { + if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) { + *should = false; + } + }); + + REGISTER_VB_SHOULD(VB_PLAY_THROW_ANIMATION, { + Player *player = GET_PLAYER(gPlayState); + Actor* interactRangeActor = player->interactRangeActor; + s32 interactActorId = interactRangeActor->id; + LinkAnimationHeader* anim = static_cast(opt); + + // Same actor is used for small and large silver rocks, use actor params to identify large ones + bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1; + if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) && (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) { + *should = false; + LinkAnimation_PlayOnceSetSpeed(gPlayState, &player->skelAnime, anim, 5.0f); + } + }); + + REGISTER_VB_SHOULD(VB_MOVE_THROWN_ACTOR, { + if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) { + Actor* heldActor = static_cast(opt); + + heldActor->shape.rot.x -= 3510; + } + }); +} diff --git a/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp b/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp index f6d2e3629..68fe71da6 100644 --- a/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp +++ b/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp @@ -11,4 +11,5 @@ void TimeSavers_Register() { SkipIntro_Register(); // SkipMiscInteractions MoveMidoInKokiriForest_Register(); + FasterHeavyBlockLift_Register(); } diff --git a/soh/soh/Enhancements/TimeSavers/TimeSavers.h b/soh/soh/Enhancements/TimeSavers/TimeSavers.h index b3b221351..d45ed7f10 100644 --- a/soh/soh/Enhancements/TimeSavers/TimeSavers.h +++ b/soh/soh/Enhancements/TimeSavers/TimeSavers.h @@ -13,5 +13,6 @@ void TimeSavers_Register(); void SkipIntro_Register(); // SkipMiscInteractions void MoveMidoInKokiriForest_Register(); +void FasterHeavyBlockLift_Register(); #endif // TIME_SAVERS_H diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 108d2f33e..f6db2e950 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -244,6 +244,8 @@ typedef enum { ``` */ VB_DRAW_AMMO_COUNT, + VB_FREEZE_LINK_FOR_BLOCK_THROW, + VB_MOVE_THROWN_ACTOR, /*** Play Cutscenes ***/ @@ -286,6 +288,7 @@ typedef enum { VB_PLAY_RAINBOW_BRIDGE_CS, // Opt: *EnBox VB_PLAY_SLOW_CHEST_CS, + VB_PLAY_THROW_ANIMATION, /*** Give Items ***/ diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 0cd6ffb09..0682f4de1 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -223,6 +223,10 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* if (actor->id == ACTOR_BG_MORI_HINERI) { break; } + // This is handled in the FasterHeavyBlockLift enhancement + if (actor->id == ACTOR_BG_HEAVY_BLOCK) { + break; + } RateLimitedSuccessChime(); *should = false; diff --git a/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c b/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c index 61d0ccb1b..6df97fcfc 100644 --- a/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c +++ b/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c @@ -7,6 +7,7 @@ #include "z_bg_heavy_block.h" #include "objects/object_heavy_object/object_heavy_object.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -320,18 +321,16 @@ void BgHeavyBlock_Wait(BgHeavyBlock* this, PlayState* play) { if (Actor_HasParent(&this->dyna.actor, play)) { this->timer = 0; - if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) { - switch (this->dyna.actor.params & 0xFF) { - case HEAVYBLOCK_BREAKABLE: - OnePointCutscene_Init(play, 4020, 270, &this->dyna.actor, MAIN_CAM); - break; - case HEAVYBLOCK_UNBREAKABLE: - OnePointCutscene_Init(play, 4021, 220, &this->dyna.actor, MAIN_CAM); - break; - case HEAVYBLOCK_UNBREAKABLE_OUTSIDE_CASTLE: - OnePointCutscene_Init(play, 4022, 210, &this->dyna.actor, MAIN_CAM); - break; - } + switch (this->dyna.actor.params & 0xFF) { + case HEAVYBLOCK_BREAKABLE: + OnePointCutscene_Init(play, 4020, 270, &this->dyna.actor, MAIN_CAM); + break; + case HEAVYBLOCK_UNBREAKABLE: + OnePointCutscene_Init(play, 4021, 220, &this->dyna.actor, MAIN_CAM); + break; + case HEAVYBLOCK_UNBREAKABLE_OUTSIDE_CASTLE: + OnePointCutscene_Init(play, 4022, 210, &this->dyna.actor, MAIN_CAM); + break; } quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), 3); @@ -369,7 +368,7 @@ void BgHeavyBlock_LiftedUp(BgHeavyBlock* this, PlayState* play) { this->timer++; - if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) { + if (GameInteractor_Should(VB_FREEZE_LINK_FOR_BLOCK_THROW, true, this)) { Player_SetCsActionWithHaltedActors(play, &player->actor, 8); } @@ -408,13 +407,10 @@ void BgHeavyBlock_Fly(BgHeavyBlock* this, PlayState* play) { Quake_SetQuakeValues(quakeIndex, 14, 2, 100, 0); Quake_SetCountdown(quakeIndex, 30); - // We don't want this arbitrarily long quake with the enhancement enabled - if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) { - quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), 2); - Quake_SetSpeed(quakeIndex, 12000); - Quake_SetQuakeValues(quakeIndex, 5, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 999); - } + quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), 2); + Quake_SetSpeed(quakeIndex, 12000); + Quake_SetQuakeValues(quakeIndex, 5, 0, 0, 0); + Quake_SetCountdown(quakeIndex, 999); SoundSource_PlaySfxAtFixedWorldPos(play, &this->dyna.actor.world.pos, 30, NA_SE_EV_ELECTRIC_EXPLOSION); 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 c5d1a65bd..24ff3dd1f 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -5096,11 +5096,7 @@ void func_8083A0F4(PlayState* play, Player* this) { anim = GET_PLAYER_ANIM(PLAYER_ANIMGROUP_carryB, this->modelAnimType); } - // Same actor is used for small and large silver rocks, use actor params to identify large ones - bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1; - if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) && (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) { - LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 5.0f); - } else { + if (GameInteractor_Should(VB_PLAY_THROW_ANIMATION, true, anim)) { LinkAnimation_PlayOnce(play, &this->skelAnime, anim); } } @@ -9842,14 +9838,12 @@ void Player_Action_80846120(Player* this, PlayState* play) { if (LinkAnimation_OnFrame(&this->skelAnime, 229.0f)) { Actor* heldActor = this->heldActor; - if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) { - // This is the difference in rotation when the animation is sped up 5x - heldActor->shape.rot.x -= 3510; + if (GameInteractor_Should(VB_MOVE_THROWN_ACTOR, true, heldActor)) { + heldActor->speedXZ = Math_SinS(heldActor->shape.rot.x) * 40.0f; + heldActor->velocity.y = Math_CosS(heldActor->shape.rot.x) * 40.0f; + heldActor->gravity = -2.0f; + heldActor->minVelocityY = -30.0f; } - heldActor->speedXZ = Math_SinS(heldActor->shape.rot.x) * 40.0f; - heldActor->velocity.y = Math_CosS(heldActor->shape.rot.x) * 40.0f; - heldActor->gravity = -2.0f; - heldActor->minVelocityY = -30.0f; Player_DetachHeldActor(play, this); return; }