diff --git a/soh/soh/Enhancements/Items/HookshotReticle.cpp b/soh/soh/Enhancements/Items/HookshotReticle.cpp new file mode 100644 index 000000000..dbc39311b --- /dev/null +++ b/soh/soh/Enhancements/Items/HookshotReticle.cpp @@ -0,0 +1,62 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/ShipInit.hpp" + +extern "C" { +extern PlayState* gPlayState; +extern SaveContext gSaveContext; +#include "macros.h" +#include "functions.h" +#include "objects/object_link_boy/object_link_boy.h" +} + +const Color_RGBA8 defaultTargetableColor = { .r = 0, .g = 255, .b = 0, .a = 255 }; +const Color_RGBA8 defaultNonTargetableColor = { .r = 255, .g = 0, .b = 0, .a = 255 }; + +#define CVAR_TARGETABLE_HOOKSHOT_NAME CVAR_ENHANCEMENT("HookshotableReticle") +#define CVAR_TARGETABLE_HOOKSHOT_DEFAULT 0 +#define CVAR_TARGETABLE_HOOKSHOT_VALUE CVarGetInteger(CVAR_TARGETABLE_HOOKSHOT_NAME, CVAR_TARGETABLE_HOOKSHOT_DEFAULT) + +#define CVAR_NON_TARGETABLE_HOOKSHOT_NAME CVAR_COSMETIC("HookshotReticle.NonTarget.Value") +#define CVAR_NON_TARGETABLE_HOOKSHOT_DEFAULT defaultNonTargetableColor +#define CVAR_NON_TARGETABLE_HOOKSHOT_VALUE \ + CVarGetColor(CVAR_NON_TARGETABLE_HOOKSHOT_NAME, CVAR_NON_TARGETABLE_HOOKSHOT_DEFAULT) + +void RegisterTargetableHookshotReticle() { + Color_RGBA8 nonTargetColor = CVAR_NON_TARGETABLE_HOOKSHOT_VALUE; + bool nonTargetColorIsNotDefault = + nonTargetColor.r != defaultNonTargetableColor.r || nonTargetColor.g != defaultNonTargetableColor.g || + nonTargetColor.b != defaultNonTargetableColor.b || nonTargetColor.a != defaultNonTargetableColor.a; + bool shouldRegister = CVAR_TARGETABLE_HOOKSHOT_VALUE || nonTargetColorIsNotDefault; + + COND_VB_SHOULD(VB_TARGETABLE_HOOKSHOT_RETICLE, shouldRegister, { + Player* player = GET_PLAYER(gPlayState); + Actor* heldActor = player->heldActor; + CollisionPoly* colPoly = va_arg(args, CollisionPoly*); + s32 bgId = va_arg(args, s32); + GraphicsContext* __gfxCtx = gPlayState->state.gfxCtx; + + const Color_RGBA8 colorTargetable = + CVarGetColor(CVAR_COSMETIC("HookshotReticle.Target.Value"), defaultTargetableColor); + const Color_RGBA8 colorNonTargetable = + CVarGetColor(CVAR_COSMETIC("HookshotReticle.NonTarget.Value"), defaultNonTargetableColor); + + gSPMatrix(OVERLAY_DISP++, SEG_ADDR(1, 0), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW); + gSPTexture(OVERLAY_DISP++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); + gDPLoadTextureBlock(OVERLAY_DISP++, gLinkAdultHookshotReticleTex, G_IM_FMT_I, G_IM_SIZ_8b, 64, 64, 0, + G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD); + if (CVAR_TARGETABLE_HOOKSHOT_VALUE && SurfaceType_IsHookshotSurface(&gPlayState->colCtx, colPoly, bgId) && + (player->heldItemAction == PLAYER_IA_HOOKSHOT || player->heldItemAction == PLAYER_IA_LONGSHOT)) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, colorTargetable.r, colorTargetable.g, colorTargetable.b, + colorTargetable.a); + } else { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, colorNonTargetable.r, colorNonTargetable.g, colorNonTargetable.b, + colorNonTargetable.a); + } + gSPVertex(OVERLAY_DISP++, (uintptr_t)gLinkAdultHookshotReticleVtx, 3, 0); + gSP1Triangle(OVERLAY_DISP++, 0, 1, 2, 0); + *should = false; + }); +} + +static RegisterShipInitFunc initFunc(RegisterTargetableHookshotReticle, + { CVAR_TARGETABLE_HOOKSHOT_NAME, CVAR_NON_TARGETABLE_HOOKSHOT_NAME }); \ No newline at end of file diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 49e74f69c..04e952982 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -2202,6 +2202,7 @@ void ResetColor(CosmeticOption& cosmeticOption) { ResetColor(cosmeticOptions.at("Kaleido.SaveC")); ResetColor(cosmeticOptions.at("Kaleido.SaveD")); } + ShipInit::Init(cosmeticOption.valuesCvar); } void DrawCosmeticRow(CosmeticOption& cosmeticOption) { diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 2d709d1d8..5b11ce543 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2200,6 +2200,15 @@ typedef enum { // - `*s16` - timer value VB_SWITCH_TIMER_TICK, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*CollisionPoly + // - s32 - background id` + VB_TARGETABLE_HOOKSHOT_RETICLE, + // #### `result` // ```c // (this->stateFlags1 & PLAYER_STATE1_CARRYING_ACTOR) && (this->heldActor != NULL) && diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 54000a74d..85964d457 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -1699,22 +1699,10 @@ void Player_DrawHookshotReticle(PlayState* play, Player* this, f32 hookshotRange Matrix_Scale(sp60, sp60, sp60, MTXMODE_APPLY); gSPMatrix(OVERLAY_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPMatrix(OVERLAY_DISP++, SEG_ADDR(1, 0), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW); - gSPTexture(OVERLAY_DISP++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); - gDPLoadTextureBlock(OVERLAY_DISP++, gLinkAdultHookshotReticleTex, G_IM_FMT_I, G_IM_SIZ_8b, 64, 64, 0, - G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD); - if (SurfaceType_IsHookshotSurface(&play->colCtx, colPoly, bgId) && - CVarGetInteger(CVAR_ENHANCEMENT("HookshotableReticle"), false)) { - const Color_RGBA8 defaultColor = { .r = 0, .g = 255, .b = 0, .a = 255 }; - const Color_RGBA8 color = CVarGetColor(CVAR_COSMETIC("HookshotReticle.Target.Value"), defaultColor); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, color.r, color.g, color.b, color.a); - } else { - const Color_RGBA8 defaultColor = { .r = 255, .g = 0, .b = 0, .a = 255 }; - const Color_RGBA8 color = CVarGetColor(CVAR_COSMETIC("HookshotReticle.NonTarget.Value"), defaultColor); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, color.r, color.g, color.b, color.a); + if (GameInteractor_Should(VB_TARGETABLE_HOOKSHOT_RETICLE, true, colPoly, bgId)) { + gSPSegment(OVERLAY_DISP++, 0x06, play->objectCtx.status[this->actor.objBankIndex].segment); + gSPDisplayList(OVERLAY_DISP++, gLinkAdultHookshotReticleDL); } - gSPVertex(OVERLAY_DISP++, (uintptr_t)gLinkAdultHookshotReticleVtx, 3, 0); - gSP1Triangle(OVERLAY_DISP++, 0, 1, 2, 0); CLOSE_DISPS(play->state.gfxCtx); }