From 51af06463f536baae615289398469ed00c38e2d7 Mon Sep 17 00:00:00 2001 From: Captain Kitty Cat <68467449+Captainkittyca2@users.noreply.github.com> Date: Wed, 24 Jul 2024 04:39:25 +0300 Subject: [PATCH] Item drops 3D! (#633) * Initial 3D Item Drops Toggle * Use generic hooks and other tweaks * 3d drop fixes and changes * move slime item draw to VB hook; fix arrow GID * whitespacing --------- Co-authored-by: Garrett Cox Co-authored-by: Archez --- mm/2s2h/BenGui/BenMenuBar.cpp | 5 + mm/2s2h/Enhancements/Enhancements.cpp | 1 + mm/2s2h/Enhancements/Enhancements.h | 1 + .../GameInteractor/GameInteractor.h | 1 + mm/2s2h/Enhancements/Graphics/3DItemDrops.cpp | 185 ++++++++++++++++++ mm/2s2h/Enhancements/Graphics/3DItemDrops.h | 6 + .../overlays/actors/ovl_En_Slime/z_en_slime.c | 13 +- 7 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 mm/2s2h/Enhancements/Graphics/3DItemDrops.cpp create mode 100644 mm/2s2h/Enhancements/Graphics/3DItemDrops.h diff --git a/mm/2s2h/BenGui/BenMenuBar.cpp b/mm/2s2h/BenGui/BenMenuBar.cpp index eef6b1cd4..edf218909 100644 --- a/mm/2s2h/BenGui/BenMenuBar.cpp +++ b/mm/2s2h/BenGui/BenMenuBar.cpp @@ -8,6 +8,7 @@ #include #include #include "2s2h/Enhancements/Enhancements.h" +#include "2s2h/Enhancements/Graphics/3DItemDrops.h" #include "2s2h/Enhancements/Graphics/MotionBlur.h" #include "2s2h/Enhancements/Graphics/PlayAsKafei.h" #include "2s2h/Enhancements/Modes/TimeMovesWhenYouMove.h" @@ -537,6 +538,10 @@ void DrawEnhancementsMenu() { "model and texture on the boot logo start screen" }); UIWidgets::CVarCheckbox("Bow Reticle", "gEnhancements.Graphics.BowReticle", { .tooltip = "Gives the bow a reticle when you draw an arrow" }); + if (UIWidgets::CVarCheckbox("3D Item Drops", "gEnhancements.Graphics.3DItemDrops", + { .tooltip = "Makes item drops 3D" })) { + Register3DItemDrops(); + } UIWidgets::CVarCheckbox( "Disable Black Bar Letterboxes", "gEnhancements.Graphics.DisableBlackBars", { .tooltip = "Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be " diff --git a/mm/2s2h/Enhancements/Enhancements.cpp b/mm/2s2h/Enhancements/Enhancements.cpp index 663f257c4..a5163d2aa 100644 --- a/mm/2s2h/Enhancements/Enhancements.cpp +++ b/mm/2s2h/Enhancements/Enhancements.cpp @@ -29,6 +29,7 @@ void InitEnhancements() { // Graphics RegisterDisableBlackBars(); + Register3DItemDrops(); // Masks RegisterFastTransformation(); diff --git a/mm/2s2h/Enhancements/Enhancements.h b/mm/2s2h/Enhancements/Enhancements.h index 57c54f414..4d6dd518d 100644 --- a/mm/2s2h/Enhancements/Enhancements.h +++ b/mm/2s2h/Enhancements/Enhancements.h @@ -23,6 +23,7 @@ #include "Restorations/PowerCrouchStab.h" #include "Restorations/SideRoll.h" #include "Restorations/TatlISG.h" +#include "Graphics/3DItemDrops.h" #include "Graphics/PlayAsKafei.h" #include "Player/Player.h" #include "Songs/EnableSunsSong.h" diff --git a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h index 1b2fdb2e9..365a0f182 100644 --- a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h +++ b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h @@ -55,6 +55,7 @@ typedef enum { GI_VB_FLIP_HOP_VARIABLE, GI_VB_DISABLE_LETTERBOX, GI_VB_CLOCK_TOWER_OPENING_CONSIDER_THIS_FIRST_CYCLE, + GI_VB_DRAW_SLIME_BODY_ITEM, } GIVanillaBehavior; typedef enum { diff --git a/mm/2s2h/Enhancements/Graphics/3DItemDrops.cpp b/mm/2s2h/Enhancements/Graphics/3DItemDrops.cpp new file mode 100644 index 000000000..f64312c63 --- /dev/null +++ b/mm/2s2h/Enhancements/Graphics/3DItemDrops.cpp @@ -0,0 +1,185 @@ +#include "3DItemDrops.h" +#include "libultraship/libultraship.h" +#include "2s2h/Enhancements/GameInteractor/GameInteractor.h" + +extern "C" { +#include "z64.h" +#include "functions.h" +#include "overlays/actors/ovl_En_Slime/z_en_slime.h" +extern PlayState* gPlayState; +void EnItem00_Draw(Actor* thisx, PlayState* play); +} + +bool ItemShouldSpinWhen3D(Actor* actor) { + EnItem00* enItem00 = (EnItem00*)actor; + + // Exclude actors that already have spin normally, or shouldn't spin ever + if ((actor->params <= ITEM00_RUPEE_RED) || ((actor->params == ITEM00_RECOVERY_HEART) && (enItem00->unk152 < 0)) || + (actor->params == ITEM00_HEART_PIECE) || (actor->params == ITEM00_HEART_CONTAINER) || + (actor->params == ITEM00_RUPEE_HUGE) || (actor->params == ITEM00_RUPEE_PURPLE) || + (actor->params == ITEM00_SHIELD_HERO) || (actor->params == ITEM00_MAP) || (actor->params == ITEM00_COMPASS)) { + return false; + } + + return true; +} + +void EnItem00_3DItemsDraw(Actor* actor, PlayState* play) { + EnItem00* enItem00 = (EnItem00*)actor; + + if (!(enItem00->unk14E & enItem00->unk150)) { + switch (enItem00->actor.params) { + case ITEM00_RUPEE_GREEN: + Matrix_Scale(25.0f, 25.0f, 25.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_RUPEE_GREEN); + break; + case ITEM00_RUPEE_BLUE: + Matrix_Scale(25.0f, 25.0f, 25.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_RUPEE_BLUE); + break; + case ITEM00_RUPEE_RED: + Matrix_Scale(25.0f, 25.0f, 25.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_RUPEE_RED); + break; + case ITEM00_RUPEE_HUGE: + Matrix_Scale(17.5f, 17.5f, 17.5f, MTXMODE_APPLY); + GetItem_Draw(play, GID_RUPEE_HUGE); + break; + case ITEM00_RUPEE_PURPLE: + Matrix_Scale(17.5f, 17.5f, 17.5f, MTXMODE_APPLY); + GetItem_Draw(play, GID_RUPEE_PURPLE); + break; + case ITEM00_HEART_PIECE: + Matrix_Scale(16.0f, 16.0f, 16.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_HEART_PIECE); + break; + case ITEM00_HEART_CONTAINER: + Matrix_Scale(16.0f, 16.0f, 16.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_HEART_CONTAINER); + break; + case ITEM00_RECOVERY_HEART: + Matrix_Scale(16.0f, 16.0f, 16.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_RECOVERY_HEART); + break; + case ITEM00_BOMBS_A: + case ITEM00_BOMBS_B: + case ITEM00_BOMBS_0: + Matrix_Scale(8.0f, 8.0f, 8.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_BOMB); + break; + case ITEM00_ARROWS_10: + Matrix_Scale(7.0f, 7.0f, 7.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_ARROWS_SMALL); + break; + case ITEM00_ARROWS_30: + Matrix_Scale(7.0f, 7.0f, 7.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_ARROWS_MEDIUM); + break; + case ITEM00_ARROWS_40: + case ITEM00_ARROWS_50: + Matrix_Scale(7.0f, 7.0f, 7.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_ARROWS_LARGE); + break; + case ITEM00_MAGIC_JAR_SMALL: + Matrix_Scale(8.0f, 8.0f, 8.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_MAGIC_JAR_SMALL); + break; + case ITEM00_MAGIC_JAR_BIG: + Matrix_Scale(8.0f, 8.0f, 8.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_MAGIC_JAR_BIG); + break; + case ITEM00_DEKU_STICK: + Matrix_Scale(7.5f, 7.5f, 7.5f, MTXMODE_APPLY); + GetItem_Draw(play, GID_DEKU_STICK); + break; + case ITEM00_SMALL_KEY: + Matrix_Scale(8.0f, 8.0f, 8.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_KEY_SMALL); + break; + case ITEM00_DEKU_NUTS_1: + case ITEM00_DEKU_NUTS_10: + Matrix_Scale(9.0f, 9.0f, 9.0f, MTXMODE_APPLY); + GetItem_Draw(play, GID_DEKU_NUTS); + break; + case ITEM00_SHIELD_HERO: + GetItem_Draw(play, GID_SHIELD_HERO); + break; + case ITEM00_MAP: + GetItem_Draw(play, GID_DUNGEON_MAP); + break; + case ITEM00_COMPASS: + GetItem_Draw(play, GID_COMPASS); + break; + } + } +} + +void DrawSlime3DItem(GIVanillaBehavior _, bool* should, void* opt) { + *should = false; + EnSlime* slime = static_cast(opt); + + // Rotate 3D item with chu body + Matrix_RotateYS(slime->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_Scale(0.25f, 0.25f, 0.25f, MTXMODE_APPLY); + + switch (slime->actor.params) { + case EN_SLIME_TYPE_RED: + GetItem_Draw(gPlayState, GID_RECOVERY_HEART); + break; + case EN_SLIME_TYPE_GREEN: + GetItem_Draw(gPlayState, GID_MAGIC_JAR_SMALL); + break; + case EN_SLIME_TYPE_YELLOW: + GetItem_Draw(gPlayState, GID_ARROWS_SMALL); + break; + } +} + +void Register3DItemDrops() { + static HOOK_ID actorInitHookID = 0; + static HOOK_ID actorUpdateHookID = 0; + static HOOK_ID slimeVBHookID = 0; + GameInteractor::Instance->UnregisterGameHookForID(actorInitHookID); + GameInteractor::Instance->UnregisterGameHookForID(actorUpdateHookID); + GameInteractor::Instance->UnregisterGameHookForID(slimeVBHookID); + actorInitHookID = 0; + actorUpdateHookID = 0; + slimeVBHookID = 0; + + if (gPlayState != NULL) { + Actor* actor = gPlayState->actorCtx.actorLists[ACTORCAT_MISC].first; + + while (actor != NULL) { + if (actor->id == ACTOR_EN_ITEM00) { + if (CVarGetInteger("gEnhancements.Graphics.3DItemDrops", 0)) { + actor->draw = EnItem00_3DItemsDraw; + } else { + actor->draw = EnItem00_Draw; + + // Reset rotation for bill-boarded sprites + if (ItemShouldSpinWhen3D(actor)) { + actor->shape.rot.y = 0; + } + } + } + + actor = actor->next; + } + } + + if (!CVarGetInteger("gEnhancements.Graphics.3DItemDrops", 0)) { + return; + } + + actorInitHookID = GameInteractor::Instance->RegisterGameHookForID( + ACTOR_EN_ITEM00, [](Actor* actor) { actor->draw = EnItem00_3DItemsDraw; }); + actorUpdateHookID = GameInteractor::Instance->RegisterGameHookForID( + ACTOR_EN_ITEM00, [](Actor* actor) { + // Add spin to normally bill-boarded items + if (ItemShouldSpinWhen3D(actor)) { + actor->shape.rot.y += 0x3C0; + } + }); + slimeVBHookID = GameInteractor::Instance->RegisterGameHookForID( + GI_VB_DRAW_SLIME_BODY_ITEM, DrawSlime3DItem); +} diff --git a/mm/2s2h/Enhancements/Graphics/3DItemDrops.h b/mm/2s2h/Enhancements/Graphics/3DItemDrops.h new file mode 100644 index 000000000..2801aaac2 --- /dev/null +++ b/mm/2s2h/Enhancements/Graphics/3DItemDrops.h @@ -0,0 +1,6 @@ +#ifndef GRAPHICS_3D_ITEM_DROPS_H +#define GRAPHICS_3D_ITEM_DROPS_H + +void Register3DItemDrops(); + +#endif // GRAPHICS_3D_ITEM_DROPS_H diff --git a/mm/src/overlays/actors/ovl_En_Slime/z_en_slime.c b/mm/src/overlays/actors/ovl_En_Slime/z_en_slime.c index ff1b3322e..fcc729cdd 100644 --- a/mm/src/overlays/actors/ovl_En_Slime/z_en_slime.c +++ b/mm/src/overlays/actors/ovl_En_Slime/z_en_slime.c @@ -7,6 +7,8 @@ #include "z_en_slime.h" #include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h" +#include "2s2h/Enhancements/GameInteractor/GameInteractor.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_200) #define THIS ((EnSlime*)thisx) @@ -1239,11 +1241,14 @@ void EnSlime_Draw(Actor* thisx, PlayState* play) { Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y + (2000.0f * this->actor.scale.y), this->actor.world.pos.z, MTXMODE_NEW); - Matrix_Scale(0.03f, 0.03f, 0.03f, MTXMODE_APPLY); - gSPSegment(POLY_OPA_DISP++, 8, (uintptr_t)this->itemDropTex); - gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, gItemDropDL); + if (GameInteractor_Should(GI_VB_DRAW_SLIME_BODY_ITEM, true, this)) { + Matrix_Scale(0.03f, 0.03f, 0.03f, MTXMODE_APPLY); + + gSPSegment(POLY_OPA_DISP++, 8, (uintptr_t)this->itemDropTex); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gItemDropDL); + } } Actor_DrawDamageEffects(play, &this->actor, this->bodyPartsPos, EN_SLIME_BODYPART_MAX, this->drawDmgEffScale,