From 509985f5b51ca1f113d5c100ff91a7ebe392e252 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Thu, 14 Dec 2023 00:24:58 -0600 Subject: [PATCH 1/7] Bomb Arrows --- soh/include/variables.h | 2 +- soh/include/z64item.h | 171 +++++++++--------- soh/include/z64player.h | 8 +- soh/src/code/code_80097A00.c | 1 + soh/src/code/z_parameter.c | 12 +- soh/src/code/z_player_lib.c | 16 +- .../overlays/actors/ovl_En_Arrow/z_en_arrow.c | 7 +- .../overlays/actors/ovl_En_Arrow/z_en_arrow.h | 2 +- soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c | 145 ++++++++++++++- soh/src/overlays/actors/ovl_En_Bom/z_en_bom.h | 5 +- .../actors/ovl_player_actor/z_player.c | 35 ++-- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 12 +- 12 files changed, 292 insertions(+), 124 deletions(-) diff --git a/soh/include/variables.h b/soh/include/variables.h index 2bad8335c99..ed64357f7f1 100644 --- a/soh/include/variables.h +++ b/soh/include/variables.h @@ -99,7 +99,7 @@ extern "C" extern u16 gUpgradeCapacities[8][4]; extern u32 gGsFlagsMasks[4]; extern u32 gGsFlagsShifts[4]; - extern void* gItemIcons[0x82]; + extern void* gItemIcons[0x83]; extern u8 gItemAgeReqs[]; extern u8 gSlotAgeReqs[]; extern u8 gItemSlots[56]; diff --git a/soh/include/z64item.h b/soh/include/z64item.h index 1fc919a45f6..5aa02469afa 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -221,91 +221,92 @@ typedef enum { /* 0x44 */ ITEM_BOOTS_KOKIRI, /* 0x45 */ ITEM_BOOTS_IRON, /* 0x46 */ ITEM_BOOTS_HOVER, - /* 0x47 */ ITEM_BULLET_BAG_30, - /* 0x48 */ ITEM_BULLET_BAG_40, - /* 0x49 */ ITEM_BULLET_BAG_50, - /* 0x4A */ ITEM_QUIVER_30, - /* 0x4B */ ITEM_QUIVER_40, - /* 0x4C */ ITEM_QUIVER_50, - /* 0x4D */ ITEM_BOMB_BAG_20, - /* 0x4E */ ITEM_BOMB_BAG_30, - /* 0x4F */ ITEM_BOMB_BAG_40, - /* 0x50 */ ITEM_BRACELET, - /* 0x51 */ ITEM_GAUNTLETS_SILVER, - /* 0x52 */ ITEM_GAUNTLETS_GOLD, - /* 0x53 */ ITEM_SCALE_SILVER, - /* 0x54 */ ITEM_SCALE_GOLDEN, - /* 0x55 */ ITEM_SWORD_KNIFE, - /* 0x56 */ ITEM_WALLET_ADULT, - /* 0x57 */ ITEM_WALLET_GIANT, - /* 0x58 */ ITEM_SEEDS, - /* 0x59 */ ITEM_FISHING_POLE, - /* 0x5A */ ITEM_SONG_MINUET, - /* 0x5B */ ITEM_SONG_BOLERO, - /* 0x5C */ ITEM_SONG_SERENADE, - /* 0x5D */ ITEM_SONG_REQUIEM, - /* 0x5E */ ITEM_SONG_NOCTURNE, - /* 0x5F */ ITEM_SONG_PRELUDE, - /* 0x60 */ ITEM_SONG_LULLABY, - /* 0x61 */ ITEM_SONG_EPONA, - /* 0x62 */ ITEM_SONG_SARIA, - /* 0x63 */ ITEM_SONG_SUN, - /* 0x64 */ ITEM_SONG_TIME, - /* 0x65 */ ITEM_SONG_STORMS, - /* 0x66 */ ITEM_MEDALLION_FOREST, - /* 0x67 */ ITEM_MEDALLION_FIRE, - /* 0x68 */ ITEM_MEDALLION_WATER, - /* 0x69 */ ITEM_MEDALLION_SPIRIT, - /* 0x6A */ ITEM_MEDALLION_SHADOW, - /* 0x6B */ ITEM_MEDALLION_LIGHT, - /* 0x6C */ ITEM_KOKIRI_EMERALD, - /* 0x6D */ ITEM_GORON_RUBY, - /* 0x6E */ ITEM_ZORA_SAPPHIRE, - /* 0x6F */ ITEM_STONE_OF_AGONY, - /* 0x70 */ ITEM_GERUDO_CARD, - /* 0x71 */ ITEM_SKULL_TOKEN, - /* 0x72 */ ITEM_HEART_CONTAINER, - /* 0x73 */ ITEM_HEART_PIECE, - /* 0x74 */ ITEM_KEY_BOSS, - /* 0x75 */ ITEM_COMPASS, - /* 0x76 */ ITEM_DUNGEON_MAP, - /* 0x77 */ ITEM_KEY_SMALL, - /* 0x78 */ ITEM_MAGIC_SMALL, - /* 0x79 */ ITEM_MAGIC_LARGE, - /* 0x7A */ ITEM_HEART_PIECE_2, - /* 0x7B */ ITEM_SINGLE_MAGIC, - /* 0x7C */ ITEM_DOUBLE_MAGIC, - /* 0x7D */ ITEM_DOUBLE_DEFENSE, - /* 0x7E */ ITEM_INVALID_4, - /* 0x7F */ ITEM_INVALID_5, - /* 0x80 */ ITEM_INVALID_6, - /* 0x81 */ ITEM_INVALID_7, - /* 0x82 */ ITEM_MILK, - /* 0x83 */ ITEM_HEART, - /* 0x84 */ ITEM_RUPEE_GREEN, - /* 0x85 */ ITEM_RUPEE_BLUE, - /* 0x86 */ ITEM_RUPEE_RED, - /* 0x87 */ ITEM_RUPEE_PURPLE, - /* 0x88 */ ITEM_RUPEE_GOLD, - /* 0x89 */ ITEM_INVALID_8, - /* 0x8A */ ITEM_STICKS_5, - /* 0x8B */ ITEM_STICKS_10, - /* 0x8C */ ITEM_NUTS_5, - /* 0x8D */ ITEM_NUTS_10, - /* 0x8E */ ITEM_BOMBS_5, - /* 0x8F */ ITEM_BOMBS_10, - /* 0x90 */ ITEM_BOMBS_20, - /* 0x91 */ ITEM_BOMBS_30, - /* 0x92 */ ITEM_ARROWS_SMALL, - /* 0x93 */ ITEM_ARROWS_MEDIUM, - /* 0x94 */ ITEM_ARROWS_LARGE, - /* 0x95 */ ITEM_SEEDS_30, - /* 0x96 */ ITEM_BOMBCHUS_5, - /* 0x97 */ ITEM_BOMBCHUS_20, - /* 0x98 */ ITEM_STICK_UPGRADE_20, - /* 0x99 */ ITEM_STICK_UPGRADE_30, - /* 0x9A */ ITEM_NUT_UPGRADE_30, - /* 0x9B */ ITEM_NUT_UPGRADE_40, + ITEM_BOW_ARROW_BOMB, + /* 0x48 */ ITEM_BULLET_BAG_30, + /* 0x49 */ ITEM_BULLET_BAG_40, + /* 0x4a */ ITEM_BULLET_BAG_50, + /* 0x4B */ ITEM_QUIVER_30, + /* 0x4C */ ITEM_QUIVER_40, + /* 0x4D */ ITEM_QUIVER_50, + /* 0x4E */ ITEM_BOMB_BAG_20, + /* 0x4F */ ITEM_BOMB_BAG_30, + /* 0x50 */ ITEM_BOMB_BAG_40, + /* 0x51 */ ITEM_BRACELET, + /* 0x52 */ ITEM_GAUNTLETS_SILVER, + /* 0x53 */ ITEM_GAUNTLETS_GOLD, + /* 0x54 */ ITEM_SCALE_SILVER, + /* 0x55 */ ITEM_SCALE_GOLDEN, + /* 0x56 */ ITEM_SWORD_KNIFE, + /* 0x57 */ ITEM_WALLET_ADULT, + /* 0x58 */ ITEM_WALLET_GIANT, + /* 0x59 */ ITEM_SEEDS, + /* 0x5a */ ITEM_FISHING_POLE, + /* 0x5B */ ITEM_SONG_MINUET, + /* 0x5C */ ITEM_SONG_BOLERO, + /* 0x5D */ ITEM_SONG_SERENADE, + /* 0x5E */ ITEM_SONG_REQUIEM, + /* 0x5F */ ITEM_SONG_NOCTURNE, + /* 0x60 */ ITEM_SONG_PRELUDE, + /* 0x61 */ ITEM_SONG_LULLABY, + /* 0x62 */ ITEM_SONG_EPONA, + /* 0x63 */ ITEM_SONG_SARIA, + /* 0x64 */ ITEM_SONG_SUN, + /* 0x65 */ ITEM_SONG_TIME, + /* 0x66 */ ITEM_SONG_STORMS, + /* 0x67 */ ITEM_MEDALLION_FOREST, + /* 0x68 */ ITEM_MEDALLION_FIRE, + /* 0x69 */ ITEM_MEDALLION_WATER, + /* 0x6a */ ITEM_MEDALLION_SPIRIT, + /* 0x6B */ ITEM_MEDALLION_SHADOW, + /* 0x6C */ ITEM_MEDALLION_LIGHT, + /* 0x6D */ ITEM_KOKIRI_EMERALD, + /* 0x6E */ ITEM_GORON_RUBY, + /* 0x6F */ ITEM_ZORA_SAPPHIRE, + /* 0x70 */ ITEM_STONE_OF_AGONY, + /* 0x71 */ ITEM_GERUDO_CARD, + /* 0x72 */ ITEM_SKULL_TOKEN, + /* 0x73 */ ITEM_HEART_CONTAINER, + /* 0x74 */ ITEM_HEART_PIECE, + /* 0x75 */ ITEM_KEY_BOSS, + /* 0x76 */ ITEM_COMPASS, + /* 0x77 */ ITEM_DUNGEON_MAP, + /* 0x78 */ ITEM_KEY_SMALL, + /* 0x79 */ ITEM_MAGIC_SMALL, + /* 0x7a */ ITEM_MAGIC_LARGE, + /* 0x7B */ ITEM_HEART_PIECE_2, + /* 0x7C */ ITEM_SINGLE_MAGIC, + /* 0x7D */ ITEM_DOUBLE_MAGIC, + /* 0x7E */ ITEM_DOUBLE_DEFENSE, + /* 0x7F */ ITEM_INVALID_4, + /* 0x80 */ ITEM_INVALID_5, + /* 0x81 */ ITEM_INVALID_6, + /* 0x82 */ ITEM_INVALID_7, + /* 0x83 */ ITEM_MILK, + /* 0x84 */ ITEM_HEART, + /* 0x85 */ ITEM_RUPEE_GREEN, + /* 0x86 */ ITEM_RUPEE_BLUE, + /* 0x87 */ ITEM_RUPEE_RED, + /* 0x88 */ ITEM_RUPEE_PURPLE, + /* 0x89 */ ITEM_RUPEE_GOLD, + /* 0x8a */ ITEM_INVALID_8, + /* 0x8B */ ITEM_STICKS_5, + /* 0x8C */ ITEM_STICKS_10, + /* 0x8D */ ITEM_NUTS_5, + /* 0x8E */ ITEM_NUTS_10, + /* 0x8F */ ITEM_BOMBS_5, + /* 0x90 */ ITEM_BOMBS_10, + /* 0x91 */ ITEM_BOMBS_20, + /* 0x92 */ ITEM_BOMBS_30, + /* 0x93 */ ITEM_ARROWS_SMALL, + /* 0x94 */ ITEM_ARROWS_MEDIUM, + /* 0x95 */ ITEM_ARROWS_LARGE, + /* 0x96 */ ITEM_SEEDS_30, + /* 0x97 */ ITEM_BOMBCHUS_5, + /* 0x98 */ ITEM_BOMBCHUS_20, + /* 0x99 */ ITEM_STICK_UPGRADE_20, + /* 0x9a */ ITEM_STICK_UPGRADE_30, + /* 0x9B */ ITEM_NUT_UPGRADE_30, + /* 0x9C */ ITEM_NUT_UPGRADE_40, /* 0xFC */ ITEM_LAST_USED = 0xFC, /* 0xFE */ ITEM_NONE_FE = 0xFE, /* 0xFF */ ITEM_NONE = 0xFF diff --git a/soh/include/z64player.h b/soh/include/z64player.h index ff30cc17094..968c3ca0058 100644 --- a/soh/include/z64player.h +++ b/soh/include/z64player.h @@ -77,7 +77,7 @@ typedef enum { /* 0x09 */ PLAYER_IA_BOW_FIRE, /* 0x0A */ PLAYER_IA_BOW_ICE, /* 0x0B */ PLAYER_IA_BOW_LIGHT, - /* 0x0C */ PLAYER_IA_BOW_0C, + /* 0x0C */ PLAYER_IA_BOW_BOMB, /* 0x0D */ PLAYER_IA_BOW_0D, /* 0x0E */ PLAYER_IA_BOW_0E, /* 0x0F */ PLAYER_IA_SLINGSHOT, @@ -426,14 +426,14 @@ typedef struct { #define PLAYER_STATE1_ENEMY_TARGET (1 << 4) #define PLAYER_STATE1_INPUT_DISABLED (1 << 5) #define PLAYER_STATE1_TEXT_ON_SCREEN (1 << 6) -#define PLAYER_STATE1_DEAD (1 << 7) +#define PLAYER_STATE1_DEAD (1 << 7) #define PLAYER_STATE1_START_PUTAWAY (1 << 8) #define PLAYER_STATE1_READY_TO_FIRE (1 << 9) #define PLAYER_STATE1_GETTING_ITEM (1 << 10) #define PLAYER_STATE1_ITEM_OVER_HEAD (1 << 11) #define PLAYER_STATE1_CHARGING_SPIN_ATTACK (1 << 12) #define PLAYER_STATE1_HANGING_OFF_LEDGE (1 << 13) -#define PLAYER_STATE1_CLIMBING_LEDGE (1 << 14) +#define PLAYER_STATE1_CLIMBING_LEDGE (1 << 14) #define PLAYER_STATE1_TARGETING (1 << 15) #define PLAYER_STATE1_TARGET_LOCKED (1 << 16) #define PLAYER_STATE1_TARGET_NOTHING (1 << 17) @@ -490,7 +490,7 @@ typedef struct { #define PLAYER_STATE3_PAUSE_ACTION_FUNC (1 << 2) #define PLAYER_STATE3_FINISHED_ATTACKING (1 << 3) #define PLAYER_STATE3_CHECK_FLOOR_WATER_COLLISION (1 << 4) -#define PLAYER_STATE3_FORCE_PULL_OCARINA (1 << 5) +#define PLAYER_STATE3_FORCE_PULL_OCARINA (1 << 5) #define PLAYER_STATE3_RESTORE_NAYRUS_LOVE (1 << 6) // Set by ocarina effects actors when destroyed to signal Nayru's Love may be restored (see `ACTOROVL_ALLOC_ABSOLUTE`) #define PLAYER_STATE3_HOOKSHOT_TRAVELLING (1 << 7) //Travelling to target diff --git a/soh/src/code/code_80097A00.c b/soh/src/code/code_80097A00.c index eb83738e360..49eab232998 100644 --- a/soh/src/code/code_80097A00.c +++ b/soh/src/code/code_80097A00.c @@ -108,6 +108,7 @@ void* gItemIcons[] = { gItemIconBootsKokiriTex, gItemIconBootsIronTex, gItemIconBootsHoverTex, + gItemIconBowFireTex, gItemIconBulletBag30Tex, gItemIconBulletBag40Tex, gItemIconBulletBag50Tex, diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 20debfd79e2..495825e9d59 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -4839,14 +4839,18 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { i = gSaveContext.equips.buttonItems[button]; if ((i == ITEM_STICK) || (i == ITEM_NUT) || (i == ITEM_BOMB) || (i == ITEM_BOW) || - ((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) || (i == ITEM_SLINGSHOT) || (i == ITEM_BOMBCHU) || - (i == ITEM_BEAN)) { + ((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) || (i == ITEM_BOW_ARROW_BOMB) || (i == ITEM_SLINGSHOT) || + (i == ITEM_BOMBCHU) || (i == ITEM_BEAN)) { - if ((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) { + if (((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) || (i == ITEM_BOW_ARROW_BOMB)) { i = ITEM_BOW; } - ammo = AMMO(i); + if (i == ITEM_BOW_ARROW_BOMB) { + ammo = MIN(AMMO(ITEM_BOW), AMMO(ITEM_BOMB)); + } else { + ammo = AMMO(i); + } gDPPipeSync(OVERLAY_DISP++); diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 820f2c67267..d579ffcb12e 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -626,7 +626,7 @@ void Player_SetModels(Player* this, s32 modelGroup) { // Left hand this->leftHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_LEFT_HAND]; this->leftHandDLists = &sPlayerDListGroups[this->leftHandType][gSaveContext.linkAge]; - + // Right hand this->rightHandType = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_RIGHT_HAND]; this->rightHandDLists = &sPlayerDListGroups[this->rightHandType][gSaveContext.linkAge]; @@ -798,6 +798,7 @@ s32 Player_HoldsBow(Player* this) { case PLAYER_IA_BOW_FIRE: case PLAYER_IA_BOW_ICE: case PLAYER_IA_BOW_LIGHT: + case PLAYER_IA_BOW_BOMB: return true; default: return false; @@ -1274,7 +1275,7 @@ s32 Player_OverrideLimbDrawGameplayCommon(PlayState* play, s32 limbIndex, Gfx** s32 Player_OverrideLimbDrawGameplayDefault(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { Player* this = (Player*)thisx; - if (!Player_OverrideLimbDrawGameplayCommon(play, limbIndex, dList, pos, rot, thisx)) + if (!Player_OverrideLimbDrawGameplayCommon(play, limbIndex, dList, pos, rot, thisx)) { if (limbIndex == PLAYER_LIMB_L_HAND) { Gfx** dLists = this->leftHandDLists; @@ -1323,7 +1324,7 @@ s32 Player_OverrideLimbDrawGameplayDefault(PlayState* play, s32 limbIndex, Gfx** } else if (limbIndex == PLAYER_LIMB_WAIST) { - + if (!Player_IsCustomLinkModel()) { *dList = ResourceMgr_LoadGfxByName( this->waistDLists[sDListsLodOffset]); // NOTE: This needs to be disabled when using custom @@ -1833,6 +1834,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve (this->heldItemAction == PLAYER_IA_BOW_FIRE) || (this->heldItemAction == PLAYER_IA_BOW_ICE) || (this->heldItemAction == PLAYER_IA_BOW_LIGHT) || + (this->heldItemAction == PLAYER_IA_BOW_BOMB) || (this->heldItemAction == PLAYER_IA_BOW) || (this->heldItemAction == PLAYER_IA_SLINGSHOT))) { if (heldActor != NULL) { @@ -1907,7 +1909,7 @@ u32 func_80091738(PlayState* play, u8* segment, SkelAnime* skelAnime) { return size + 0x8800 + 0x90; } -u8 sPauseModelGroupBySword[] = { +u8 sPauseModelGroupBySword[] = { PLAYER_MODELGROUP_SWORD, // PLAYER_SWORD_KOKIRI PLAYER_MODELGROUP_SWORD, // PLAYER_SWORD_MASTER PLAYER_MODELGROUP_BGS, // PLAYER_SWORD_BIGGORON @@ -1931,7 +1933,7 @@ s32 Player_OverrideLimbDrawPause(PlayState* play, s32 limbIndex, Gfx** dList, Ve type = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_LEFT_HAND]; sLeftHandType = type; - // SOH: Handle unexpected swordless case. Previously OOB array access is avoided, but we want the + // SOH: Handle unexpected swordless case. Previously OOB array access is avoided, but we want the // hand model-type to be set to open (otherwise it is set to holding sword model-type) if (playerSwordAndShield[0] == PLAYER_SWORD_NONE) { type = PLAYER_MODELTYPE_LH_OPEN; @@ -1956,7 +1958,7 @@ s32 Player_OverrideLimbDrawPause(PlayState* play, s32 limbIndex, Gfx** dList, Ve } } else if (limbIndex == PLAYER_LIMB_WAIST) { type = gPlayerModelTypes[modelGroup][PLAYER_MODELGROUPENTRY_WAIST]; - + if (Player_IsCustomLinkModel()) { return 0; } @@ -2225,7 +2227,7 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f* } else { SelectedAnim=randval; } - } + } } else if ((CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_NONE) && (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_NONE)) { // if the player has no sword or shield equipped s16 randval = (rand() % (4 - 2 + 1)) + 2; // 3 animations if (randval==4) { //if its the shield anim diff --git a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c index 8b1d191a618..db1f0fd13bb 100644 --- a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c +++ b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c @@ -5,6 +5,7 @@ */ #include "z_en_arrow.h" +#include "overlays/actors/ovl_en_bom/z_en_bom.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_gi_nuts/object_gi_nuts.h" @@ -214,6 +215,7 @@ void EnArrow_Shoot(EnArrow* this, PlayState* play) { case ARROW_NORMAL_LIT: case ARROW_NORMAL_HORSE: case ARROW_NORMAL: + case ARROW_BOMB: Player_PlaySfx(&player->actor, NA_SE_IT_ARROW_SHOT); break; @@ -441,11 +443,12 @@ void EnArrow_Update(Actor* thisx, PlayState* play) { if ((this->actor.params >= ARROW_FIRE) && (this->actor.params <= ARROW_0E)) { s16 elementalActorIds[] = { ACTOR_ARROW_FIRE, ACTOR_ARROW_ICE, ACTOR_ARROW_LIGHT, - ACTOR_ARROW_FIRE, ACTOR_ARROW_FIRE, ACTOR_ARROW_FIRE }; + ACTOR_EN_BOM, ACTOR_ARROW_FIRE, ACTOR_ARROW_FIRE }; if (this->actor.child == NULL) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, elementalActorIds[this->actor.params - 3], - this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, + this->actor.params == ARROW_BOMB ? BOMB_ARROW : 0); } } else if (this->actor.params == ARROW_NORMAL_LIT) { static Vec3f velocity = { 0.0f, 0.5f, 0.0f }; diff --git a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.h b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.h index 4ee84d3315b..7e9b9c1967e 100644 --- a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.h +++ b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.h @@ -34,7 +34,7 @@ typedef enum { /* 3 */ ARROW_FIRE, /* 4 */ ARROW_ICE, /* 5 */ ARROW_LIGHT, - /* 6 */ ARROW_0C, + /* 6 */ ARROW_BOMB, /* 7 */ ARROW_0D, /* 8 */ ARROW_0E, /* 9 */ ARROW_SEED, diff --git a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c index 40adc1a6f1a..f7b263299c0 100644 --- a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c +++ b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c @@ -20,6 +20,8 @@ void EnBom_Draw(Actor* thisx, PlayState* play); void EnBom_Move(EnBom* this, PlayState* play); void EnBom_WaitForRelease(EnBom* this, PlayState* play); +void ArrowBomb_Init(EnBom* this, PlayState* play); + const ActorInit En_Bom_InitVars = { ACTOR_EN_BOM, ACTORCAT_EXPLOSIVE, @@ -93,6 +95,11 @@ void EnBom_SetupAction(EnBom* this, EnBomActionFunc actionFunc) { void EnBom_Init(Actor* thisx, PlayState* play) { EnBom* this = (EnBom*)thisx; + if (this->actor.params == BOMB_ARROW) { + ArrowBomb_Init(this, play); + return; + } + Actor_ProcessInitChain(thisx, sInitChain); ActorShape_Init(&thisx->shape, 700.0f, ActorShadow_DrawCircle, 16.0f); thisx->colChkInfo.mass = 200; @@ -205,7 +212,7 @@ void EnBom_Explode(EnBom* this, PlayState* play) { } else { this->explosionCollider.elements[0].dim.worldSphere.radius += this->actor.shape.rot.z + 8; } - + if (this->actor.params == BOMB_EXPLOSION) { CollisionCheck_SetAT(play, &play->colChkCtx, &this->explosionCollider.base); @@ -348,6 +355,52 @@ void EnBom_Update(Actor* thisx, PlayState* play2) { Audio_PlayActorSound2(thisx, NA_SE_IT_BOMB_EXPLOSION); + play->envCtx.adjLight1Color[0] = play->envCtx.adjLight1Color[1] = + play->envCtx.adjLight1Color[2] = 250; + + play->envCtx.adjAmbientColor[0] = play->envCtx.adjAmbientColor[1] = + play->envCtx.adjAmbientColor[2] = 250; + + Camera_AddQuake(&play->mainCamera, 2, 0xB, 8); + thisx->params = BOMB_EXPLOSION; + this->timer = 10; + thisx->flags |= ACTOR_FLAG_DRAW_WHILE_CULLED; + EnBom_SetupAction(this, EnBom_Explode); + } + } else if (thisx->params == BOMB_ARROW) { + dustAccel.y = 0.2f; + + // spawn spark effect on even frames + effPos = thisx->world.pos; + effPos.y += 5.0f; + if ((play->gameplayFrames % 2) == 0) { + EffectSsGSpk_SpawnFuse(play, thisx, &effPos, &effVelocity, &effAccel); + } + + Audio_PlayActorSound2(thisx, NA_SE_IT_BOMB_IGNIT - SFX_FLAG); + + effPos.y += 1.0f; + func_8002829C(play, &effPos, &effVelocity, &dustAccel, &dustColor, &dustColor, 50, 5); + + dustAccel.y = 0.2f; + effPos = thisx->world.pos; + effPos.y += 1.0f; + + if (this->timer == 0) { + effPos = thisx->world.pos; + + effPos.y += 10.0f; + + EffectSsBomb2_SpawnLayered(play, &effPos, &effVelocity, &bomb2Accel, 100, + (thisx->shape.rot.z * 6) + 19); + + effPos.y = thisx->floorHeight; + if (thisx->floorHeight > BGCHECK_Y_MIN) { + EffectSsBlast_SpawnWhiteShockwave(play, &effPos, &effVelocity, &effAccel); + } + + Audio_PlayActorSound2(thisx, NA_SE_IT_BOMB_EXPLOSION); + play->envCtx.adjLight1Color[0] = play->envCtx.adjLight1Color[1] = play->envCtx.adjLight1Color[2] = 250; @@ -364,7 +417,7 @@ void EnBom_Update(Actor* thisx, PlayState* play2) { Actor_SetFocus(thisx, 20.0f); - if (thisx->params <= BOMB_BODY) { + if (thisx->params != BOMB_EXPLOSION) { Collider_UpdateCylinder(thisx, &this->bombCollider); // if link is not holding the bomb anymore and bump conditions are met, subscribe to OC @@ -395,7 +448,7 @@ void EnBom_Draw(Actor* thisx, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); - if (thisx->params == BOMB_BODY) { + if (thisx->params != BOMB_EXPLOSION) { Gfx_SetupDL_25Opa(play->state.gfxCtx); if (!CVarGetInteger("gDisableBombBillboarding", 0)) { Matrix_ReplaceRotation(&play->billboardMtxF); @@ -415,3 +468,89 @@ void EnBom_Draw(Actor* thisx, PlayState* play) { CLOSE_DISPS(play->state.gfxCtx); } + + +#include "overlays/actors/ovl_En_Arrow/z_en_arrow.h" + +void ArrowBomb_Charge(EnBom* this, PlayState* play); +void ArrowBomb_Fly(EnBom* this, PlayState* play); + +void ArrowBomb_Init(EnBom* this, PlayState* play) { + Actor_ProcessInitChain(&this->actor, sInitChain); + ActorShape_Init(&this->actor.shape, 700.0f, ActorShadow_DrawCircle, 16.0f); + + this->flashSpeedScale = 7; + Collider_InitCylinder(play, &this->bombCollider); + Collider_InitJntSph(play, &this->explosionCollider); + Collider_SetCylinder(play, &this->bombCollider, &this->actor, &sCylinderInit); + Collider_SetJntSph(play, &this->explosionCollider, &this->actor, &sJntSphInit, &this->explosionColliderItems[0]); + this->explosionColliderItems[0].info.toucher.damage += (this->actor.shape.rot.z & 0xFF00) >> 8; + + this->actor.shape.rot.z &= 0xFF; + if (this->actor.shape.rot.z & 0x80) { + this->actor.shape.rot.z |= 0xFF00; + } + + Actor_SetScale(&this->actor, 0.003f); + + EnBom_SetupAction(this, ArrowBomb_Charge); +} + +void ArrowBomb_Charge(EnBom* this, PlayState* play) { + EnArrow* arrow = (EnArrow*)this->actor.parent; + if ((arrow == NULL) || (arrow->actor.update == NULL)) { + Actor_Kill(&this->actor); + return; + } + + // copy position and rotation from arrow + this->actor.world.pos = arrow->actor.world.pos; + f32 r = 10.0f; + f32 xrot = arrow->actor.world.rot.x; + f32 yrot = arrow->actor.world.rot.y; + this->actor.world.pos.x += r * Math_CosS(xrot) * Math_SinS(yrot); + this->actor.world.pos.y -= r * Math_SinS(xrot); + this->actor.world.pos.z += r * Math_CosS(xrot) * Math_CosS(yrot); + + this->timer = 10; + + // if arrow has no parent, player has fired the arrow + if (arrow->actor.parent == NULL) { + this->unkPos = this->actor.world.pos; + EnBom_SetupAction(this, ArrowBomb_Fly); + } +} + +void ArrowBomb_Fly(EnBom* this, PlayState* play) { + EnArrow* arrow; + f32 distanceScaled; + s32 pad; + + arrow = (EnArrow*)this->actor.parent; + if ((arrow == NULL) || (arrow->actor.update == NULL)) { + Actor_Kill(&this->actor); + return; + } + // copy position and rotation from arrow + this->actor.world.pos = arrow->actor.world.pos; + f32 r = 10.0f; + f32 xrot = arrow->actor.world.rot.x; + f32 yrot = arrow->actor.world.rot.y; + this->actor.world.pos.x += r * Math_SinS(yrot) * Math_CosS(xrot); + this->actor.world.pos.y -= r * Math_SinS(xrot); + this->actor.world.pos.z += r * Math_CosS(yrot) * Math_CosS(xrot); + + distanceScaled = Math_Vec3f_DistXYZ(&this->unkPos, &this->actor.world.pos) * (1.0f / 24.0f); + this->unk_158 = distanceScaled; + if (distanceScaled < 1.0f) { + this->unk_158 = 1.0f; + } + func_80865ECC(&this->unkPos, &this->actor.world.pos, 0.05f); + + if (arrow->hitFlags & 1) { + this->timer = 0; + this->actor.shape.rot.z = 0; + } else { + this->timer = 10; + } +} diff --git a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.h b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.h index 15e391226d8..90d7465f5f4 100644 --- a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.h +++ b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.h @@ -18,11 +18,14 @@ typedef struct EnBom { /* 0x01FC */ f32 flashIntensity; /* 0x0200 */ u8 bumpOn; /* 0x0204 */ EnBomActionFunc actionFunc; + /* 0x014C */ Vec3f unkPos; + /* 0x0158 */ f32 unk_158; } EnBom; // size = 0x0208 typedef enum { /* 0x00 */ BOMB_BODY, - /* 0x01 */ BOMB_EXPLOSION + /* 0x01 */ BOMB_EXPLOSION, + /* 0x02 */ BOMB_ARROW, } EnBomType; #endif 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 52dc2a3e448..4d013642e40 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -1062,6 +1062,7 @@ static s8 sItemActionParams[] = { PLAYER_IA_BOOTS_KOKIRI, PLAYER_IA_BOOTS_IRON, PLAYER_IA_BOOTS_HOVER, + PLAYER_IA_BOW_BOMB, }; static u8 sMaskMemory; @@ -2213,6 +2214,14 @@ s32 func_80834380(PlayState* play, Player* this, s32* itemPtr, s32* typePtr) { return play->interfaceCtx.hbaAmmo; } else if (play->shootingGalleryStatus != 0) { return play->shootingGalleryStatus; + } else if (this->heldItemAction == PLAYER_IA_BOW_BOMB) { + if (AMMO(*itemPtr) == 0) { + return 0; + } else if (AMMO(ITEM_BOMB) == 0) { + *typePtr = ARROW_NORMAL; + } else { + return MIN(AMMO(*itemPtr), AMMO(ITEM_BOMB)); + } } else { return AMMO(*itemPtr); } @@ -2224,7 +2233,7 @@ s32 func_8083442C(Player* this, PlayState* play) { s32 arrowType; s32 magicArrowType; - if ((this->heldItemAction >= PLAYER_IA_BOW_FIRE) && (this->heldItemAction <= PLAYER_IA_BOW_0E) && + if ((this->heldItemAction >= PLAYER_IA_BOW_FIRE) && (this->heldItemAction < PLAYER_IA_BOW_BOMB) && (gSaveContext.magicState != MAGIC_STATE_IDLE)) { func_80078884(NA_SE_SY_ERROR); } else { @@ -4934,7 +4943,7 @@ s32 func_8083AD4C(PlayState* play, Player* this) { if(CVarGetInteger("gBowSlingShotAmmoFix", 0)){ shouldUseBowCamera = this->heldItemAction != PLAYER_IA_SLINGSHOT; } - + cameraMode = shouldUseBowCamera ? CAM_MODE_BOWARROW : CAM_MODE_SLINGSHOT; } else { cameraMode = CAM_MODE_BOOMERANG; @@ -5378,7 +5387,7 @@ s32 func_8083BDBC(Player* this, PlayState* play) { if (sp2C == 2) { gSaveContext.sohStats.count[COUNT_BACKFLIPS]++; } - + return 1; } } @@ -6106,8 +6115,8 @@ void func_8083DFE0(Player* this, f32* arg1, s16* arg2) { if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) == BUNNY_HOOD_FAST_AND_JUMP && this->currentMask == PLAYER_MASK_BUNNY) { maxSpeed *= 1.5f; - } - + } + if (CVarGetInteger("gEnableWalkModify", 0) && !CVarGetInteger("gWalkModifierDoesntChangeJump", 0)) { if (CVarGetInteger("gWalkSpeedToggle", 0)) { if (gWalkSpeedToggle1) { @@ -6350,8 +6359,8 @@ s32 func_8083E5A8(Player* this, PlayState* play) { uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY || Item_CheckObtainability(giEntry.itemId) == ITEM_NONE || IS_RANDO; // Only skip cutscenes for drops when they're items/consumables from bushes/rocks/enemies. - uint8_t isDropToSkip = (interactedActor->id == ACTOR_EN_ITEM00 && interactedActor->params != 6 && interactedActor->params != 17) || - interactedActor->id == ACTOR_EN_KAREBABA || + uint8_t isDropToSkip = (interactedActor->id == ACTOR_EN_ITEM00 && interactedActor->params != 6 && interactedActor->params != 17) || + interactedActor->id == ACTOR_EN_KAREBABA || interactedActor->id == ACTOR_EN_DEKUBABA; // Skip cutscenes from picking up consumables with "Fast Pickup Text" enabled, even when the player never picked it up before. @@ -7759,7 +7768,7 @@ void func_80842180(Player* this, PlayState* play) { if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) { sp2C *= 1.5f; } - + if (CVarGetInteger("gEnableWalkModify", 0)) { if (CVarGetInteger("gWalkSpeedToggle", 0)) { if (gWalkSpeedToggle1) { @@ -11187,7 +11196,7 @@ void Player_Update(Actor* thisx, PlayState* play) { // Play fan sound (too annoying) //func_8002F974(&player->actor, NA_SE_EV_WIND_TRAP - SFX_FLAG); } - + GameInteractor_ExecuteOnPlayerUpdate(); } @@ -11238,7 +11247,7 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList, MATRIX_TOMTX(sp70); } - + if (this->currentMask != PLAYER_MASK_BUNNY || !CVarGetInteger("gHideBunnyHood", 0)) { gSPDisplayList(POLY_OPA_DISP++, sMaskDlists[this->currentMask - 1]); } @@ -13569,7 +13578,7 @@ void func_8084F88C(Player* this, PlayState* play) { play->nextEntranceIndex = 0x0088; } else if (this->unk_84F < 0) { Play_TriggerRespawn(play); - // In ER, handle DMT and other special void outs to respawn from last entrance from grotto + // In ER, handle DMT and other special void outs to respawn from last entrance from grotto if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) { Grotto_ForceRegularVoidOut(); } @@ -14996,7 +15005,7 @@ void func_80852648(PlayState* play, Player* this, CsCmdActorAction* arg2) { this->heldItemId = ITEM_NONE; this->modelGroup = this->nextModelGroup = Player_ActionToModelGroup(this, PLAYER_IA_NONE); this->leftHandDLists = gPlayerLeftHandOpenDLs; - + // If MS sword is shuffled and not in the players inventory, then we need to unequip the current sword // and set swordless flag to mimic Link having his weapon knocked out of his hand in the Ganon fight if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) { @@ -15005,7 +15014,7 @@ void func_80852648(PlayState* play, Player* this, CsCmdActorAction* arg2) { Flags_SetInfTable(INFTABLE_SWORDLESS); return; } - + Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_MASTER); gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; Inventory_DeleteEquipment(play, EQUIP_TYPE_SWORD); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 665c95b81af..c38c3cd7496 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -42,6 +42,7 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 130, 130, 130, pauseCtx->alpha); } else if ((item == ITEM_BOMB && AMMO(item) == CUR_CAPACITY(UPG_BOMB_BAG)) || (item == ITEM_BOW && AMMO(item) == CUR_CAPACITY(UPG_QUIVER)) || + (item == ITEM_BOW_ARROW_BOMB && MIN(AMMO(ITEM_BOW), AMMO(ITEM_BOMB)) == MIN(CUR_CAPACITY(UPG_QUIVER), CUR_CAPACITY(UPG_BOMB_BAG))) || (item == ITEM_SLINGSHOT && AMMO(item) == CUR_CAPACITY(UPG_BULLET_BAG)) || (item == ITEM_STICK && AMMO(item) == CUR_CAPACITY(UPG_STICKS)) || (item == ITEM_NUT && AMMO(item) == CUR_CAPACITY(UPG_NUTS)) || (item == ITEM_BOMBCHU && ammo == 50) || @@ -813,8 +814,8 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { { C_DOWN_BUTTON_X+X_Margins_CD, C_DOWN_BUTTON_Y+Y_Margins_CD }, { C_RIGHT_BUTTON_X+X_Margins_CR, C_RIGHT_BUTTON_Y+Y_Margins_CR }, { DPAD_UP_X+X_Margins_DPad_Items, DPAD_UP_Y+Y_Margins_DPad_Items }, - { DPAD_DOWN_X+X_Margins_DPad_Items, DPAD_DOWN_Y+Y_Margins_DPad_Items }, - { DPAD_LEFT_X+X_Margins_DPad_Items, DPAD_LEFT_Y+Y_Margins_DPad_Items }, + { DPAD_DOWN_X+X_Margins_DPad_Items, DPAD_DOWN_Y+Y_Margins_DPad_Items }, + { DPAD_LEFT_X+X_Margins_DPad_Items, DPAD_LEFT_Y+Y_Margins_DPad_Items }, { DPAD_RIGHT_X+X_Margins_DPad_Items, DPAD_RIGHT_Y+Y_Margins_DPad_Items } }; s16 DPad_ItemsOffset[4][2] = { @@ -1027,11 +1028,16 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { pauseCtx->equipTargetSlot = SLOT_BOW; } } - + // If the item is on another button already, swap the two uint16_t targetButtonIndex = pauseCtx->equipTargetCBtn + 1; for (uint16_t otherSlotIndex = 0; otherSlotIndex < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); otherSlotIndex++) { + if (gSaveContext.equips.buttonItems[targetButtonIndex] == ITEM_BOW && pauseCtx->equipTargetItem == ITEM_BOMB) { + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_BOMB; + pauseCtx->equipTargetSlot = SLOT_BOW; + } + uint16_t otherButtonIndex = otherSlotIndex + 1; if (otherSlotIndex == pauseCtx->equipTargetCBtn) { continue; From f4a22cead462053985c0b7cc76f88d6e9dbe8159 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Thu, 14 Dec 2023 09:51:50 -0600 Subject: [PATCH 2/7] Bomb arrows: Improvements and fixes --- soh/src/code/z_parameter.c | 59 ++++++++++--------- soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c | 32 +++++----- .../actors/ovl_player_actor/z_player.c | 3 + .../misc/ovl_kaleido_scope/z_kaleido_item.c | 7 ++- 4 files changed, 54 insertions(+), 47 deletions(-) diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 495825e9d59..4290dcd53e9 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1441,7 +1441,7 @@ void Inventory_SwapAgeEquipment(void) { u16 shieldEquipValue; if (LINK_AGE_IN_YEARS == YEARS_CHILD) { - + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if (i != 0) { @@ -1483,13 +1483,13 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA]; gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB; gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA; - + gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) | (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && + if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && gSaveContext.equips.buttonItems[0] == ITEM_NONE) { gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); } @@ -1814,14 +1814,14 @@ u8 Return_Item(u8 itemID, ModIndex modId, ItemID returnItem) { /** * @brief Adds the given item to Link's inventory. - * + * * NOTE: This function has been edited to be safe to use with a NULL play. * If you need to add to this function, be sure you check if the play is not * NULL before doing any operations requiring it. - * - * @param play - * @param item - * @return u8 + * + * @param play + * @param item + * @return u8 */ u8 Item_Give(PlayState* play, u8 item) { lusprintf(__FILE__, __LINE__, 2, "Item Give - item: %#x", item); @@ -1902,10 +1902,10 @@ u8 Item_Give(PlayState* play, u8 item) { // In rando, when buying Giant's Knife, also check // without the Koriri Sword in case we don't have it - if (ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD) == + if (ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD) == ((1 << EQUIP_INV_SWORD_KOKIRI) | (1 << EQUIP_INV_SWORD_MASTER) | (1 << EQUIP_INV_SWORD_BIGGORON) | - (1 << EQUIP_INV_SWORD_BROKENGIANTKNIFE)) || - (IS_RANDO && ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD) == + (1 << EQUIP_INV_SWORD_BROKENGIANTKNIFE)) || + (IS_RANDO && ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD) == ((1 << EQUIP_INV_SWORD_MASTER) | (1 << EQUIP_INV_SWORD_BIGGORON) | (1 << EQUIP_INV_SWORD_BROKENGIANTKNIFE)))) { gSaveContext.inventory.equipment ^= OWNED_EQUIP_FLAG_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE); @@ -1917,7 +1917,7 @@ u8 Item_Give(PlayState* play, u8 item) { } } } - + } else if (item == ITEM_SWORD_MASTER) { gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); @@ -2657,7 +2657,7 @@ u8 Item_CheckObtainability(u8 item) { return ITEM_NONE; } } - + if ((item >= ITEM_SONG_MINUET) && (item <= ITEM_SONG_STORMS)) { return ITEM_NONE; } else if ((item >= ITEM_MEDALLION_FOREST) && (item <= ITEM_MEDALLION_LIGHT)) { @@ -2921,7 +2921,7 @@ bool Inventory_HatchPocketCucco(PlayState* play) { return Inventory_ReplaceItem(play, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO); } - if (!PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_POCKET_EGG)) { + if (!PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_POCKET_EGG)) { return 0; } @@ -2960,7 +2960,7 @@ void Interface_LoadActionLabel(InterfaceContext* interfaceCtx, u16 action, s16 l } doAction = newName[loadOffset]; } - + char* segment = interfaceCtx->doActionSegment[loadOffset]; interfaceCtx->doActionSegment[loadOffset] = action != DO_ACTION_NONE ? doAction : gEmptyTexture; gSegments[7] = interfaceCtx->doActionSegment[loadOffset]; @@ -3027,7 +3027,7 @@ void Interface_LoadActionLabelB(PlayState* play, u16 action) { } interfaceCtx->unk_1FC = action; - + char* segment = interfaceCtx->doActionSegment[1]; interfaceCtx->doActionSegment[1] = action != DO_ACTION_NONE ? doAction : gEmptyTexture; osRecvMesg(&interfaceCtx->loadQueue, NULL, OS_MESG_BLOCK); @@ -3052,7 +3052,7 @@ s32 Health_ChangeBy(PlayState* play, s16 healthChange) { if (healthChange < 0) { gSaveContext.health = 0; } - + return 0; } @@ -3121,7 +3121,7 @@ void Rupees_ChangeBy(s16 rupeeChange) { void GameplayStats_UpdateAmmoUsed(s16 item, s16 ammoUsed) { - switch (item) { + switch (item) { case ITEM_STICK: gSaveContext.sohStats.count[COUNT_AMMO_USED_STICK] += ammoUsed; break; @@ -4307,7 +4307,7 @@ void Interface_DrawItemButtons(PlayState* play) { G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - gSPWideTextureRectangle(OVERLAY_DISP++, C_Up_BTN_Pos[0]-LabelX_Navi << 2, C_Up_BTN_Pos[1]+LabelY_Navi << 2, + gSPWideTextureRectangle(OVERLAY_DISP++, C_Up_BTN_Pos[0]-LabelX_Navi << 2, C_Up_BTN_Pos[1]+LabelY_Navi << 2, (C_Up_BTN_Pos[0]-LabelX_Navi + 32) << 2, (C_Up_BTN_Pos[1]+LabelY_Navi + 8) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } @@ -4425,7 +4425,7 @@ void Interface_DrawItemButtons(PlayState* play) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, cRightButtonColor.r, cRightButtonColor.g, cRightButtonColor.b, interfaceCtx->cRightAlpha); } - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, ((u8*)gButtonBackgroundTex), 32, 32, + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, ((u8*)gButtonBackgroundTex), 32, 32, ItemIconPos[temp-1][0], ItemIconPos[temp-1][1], ItemIconWidthFactor[temp-1][0], ItemIconWidthFactor[temp-1][0], ItemIconWidthFactor[temp-1][1], ItemIconWidthFactor[temp-1][1]); @@ -4500,8 +4500,8 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { { C_DOWN_BUTTON_X+X_Margins_CD, C_DOWN_BUTTON_Y+Y_Margins_CD }, { C_RIGHT_BUTTON_X+X_Margins_CR, C_RIGHT_BUTTON_Y+Y_Margins_CR }, { DPAD_UP_X+X_Margins_DPad_Items, DPAD_UP_Y+Y_Margins_DPad_Items }, - { DPAD_DOWN_X+X_Margins_DPad_Items, DPAD_DOWN_Y+Y_Margins_DPad_Items }, - { DPAD_LEFT_X+X_Margins_DPad_Items, DPAD_LEFT_Y+Y_Margins_DPad_Items }, + { DPAD_DOWN_X+X_Margins_DPad_Items, DPAD_DOWN_Y+Y_Margins_DPad_Items }, + { DPAD_LEFT_X+X_Margins_DPad_Items, DPAD_LEFT_Y+Y_Margins_DPad_Items }, { DPAD_RIGHT_X+X_Margins_DPad_Items, DPAD_RIGHT_Y+Y_Margins_DPad_Items } }; u16 ItemsSlotsAlpha[8] = { @@ -4842,7 +4842,7 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { ((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) || (i == ITEM_BOW_ARROW_BOMB) || (i == ITEM_SLINGSHOT) || (i == ITEM_BOMBCHU) || (i == ITEM_BEAN)) { - if (((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) || (i == ITEM_BOW_ARROW_BOMB)) { + if ((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) { i = ITEM_BOW; } @@ -4865,6 +4865,7 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { } } else if (((i == ITEM_BOW) && (AMMO(i) == CUR_CAPACITY(UPG_QUIVER))) || ((i == ITEM_BOMB) && (AMMO(i) == CUR_CAPACITY(UPG_BOMB_BAG))) || + ((i == ITEM_BOW_ARROW_BOMB) && MIN(AMMO(ITEM_BOW), AMMO(ITEM_BOMB)) == MIN(CUR_CAPACITY(UPG_QUIVER), CUR_CAPACITY(UPG_BOMB_BAG))) || ((i == ITEM_SLINGSHOT) && (AMMO(i) == CUR_CAPACITY(UPG_BULLET_BAG))) || ((i == ITEM_STICK) && (AMMO(i) == CUR_CAPACITY(UPG_STICKS))) || ((i == ITEM_NUT) && (AMMO(i) == CUR_CAPACITY(UPG_NUTS))) || ((i == ITEM_BOMBCHU) && (ammo == 50)) || @@ -4881,11 +4882,11 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { } if (i != 0) { - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[i], 8, 8, + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[i], 8, 8, ItemIconPos[button][0], ItemIconPos[button][1], 8, 8, 1 << 10, 1 << 10); } - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[ammo], 8, 8, + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[ammo], 8, 8, ItemIconPos[button][0] + 6, ItemIconPos[button][1], 8, 8, 1 << 10, 1 << 10); } @@ -5390,7 +5391,7 @@ void Interface_Draw(PlayState* play) { PosY_adjust = 6; PosX_adjust = -10; } - + s16 BbtnPosX; s16 BbtnPosY; s16 X_Margins_BtnB_label; @@ -5708,7 +5709,7 @@ void Interface_Draw(PlayState* play) { CarrotsPosY = CVarGetInteger("gCarrotsPosY", 0); if (CVarGetInteger("gCarrotsPosType", 0) == 1) {//Anchor Left if (CVarGetInteger("gCarrotsUseMargins", 0) != 0) {CarrotsMargins_X = Left_HUD_Margin;}; - CarrotsPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCarrotsPosX", 0)+CarrotsMargins_X); + CarrotsPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCarrotsPosX", 0)+CarrotsMargins_X); } else if (CVarGetInteger("gCarrotsPosType", 0) == 2) {//Anchor Right if (CVarGetInteger("gCarrotsUseMargins", 0) != 0) {CarrotsMargins_X = Right_HUD_Margin;}; CarrotsPosX = OTRGetDimensionFromRightEdge(CVarGetInteger("gCarrotsPosX", 0)+CarrotsMargins_X); @@ -6218,7 +6219,7 @@ void Interface_Draw(PlayState* play) { for (svar1 = 0; svar1 < 5; svar1++) { // clang-format off //svar5 = svar5 + 8; - //svar5 = OTRGetRectDimensionFromLeftEdge(gSaveContext.timerX[svar6]); + //svar5 = OTRGetRectDimensionFromLeftEdge(gSaveContext.timerX[svar6]); OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, digitTextures[timerDigits[svar1]], 8, 16, svar5 + timerDigitLeftPos[svar1], svar2, digitWidth[svar1], VREG(42), VREG(43) << 1, @@ -6362,7 +6363,7 @@ void Interface_Update(PlayState* play) { Left_HUD_Margin = CVarGetInteger("gHUDMargin_L", 0); Right_HUD_Margin = CVarGetInteger("gHUDMargin_R", 0); Bottom_HUD_Margin = CVarGetInteger("gHUDMargin_B", 0); - + GameInteractor_ExecuteOnInterfaceUpdate(); if (CHECK_BTN_ALL(debugInput->press.button, BTN_DLEFT)) { diff --git a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c index f7b263299c0..7d53d7942fb 100644 --- a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c +++ b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c @@ -253,6 +253,9 @@ void EnBom_Explode(EnBom* this, PlayState* play) { } Actor_Kill(&this->actor); + if (this->actor.parent && this->actor.parent->id == ACTOR_EN_ARROW) { + Actor_Kill(this->actor.parent); + } } } @@ -496,6 +499,17 @@ void ArrowBomb_Init(EnBom* this, PlayState* play) { EnBom_SetupAction(this, ArrowBomb_Charge); } +void ArrowBomb_SetPosition(EnBom* this, EnArrow* arrow) { + // copy position and rotation from arrow + this->actor.world.pos = arrow->actor.world.pos; + f32 r = 8.0f; + f32 xrot = arrow->actor.world.rot.x; + f32 yrot = arrow->actor.world.rot.y; + this->actor.world.pos.x += r * Math_CosS(xrot) * Math_SinS(yrot); + this->actor.world.pos.y -= r * Math_SinS(xrot) + 2.0f; + this->actor.world.pos.z += r * Math_CosS(xrot) * Math_CosS(yrot); +} + void ArrowBomb_Charge(EnBom* this, PlayState* play) { EnArrow* arrow = (EnArrow*)this->actor.parent; if ((arrow == NULL) || (arrow->actor.update == NULL)) { @@ -503,14 +517,7 @@ void ArrowBomb_Charge(EnBom* this, PlayState* play) { return; } - // copy position and rotation from arrow - this->actor.world.pos = arrow->actor.world.pos; - f32 r = 10.0f; - f32 xrot = arrow->actor.world.rot.x; - f32 yrot = arrow->actor.world.rot.y; - this->actor.world.pos.x += r * Math_CosS(xrot) * Math_SinS(yrot); - this->actor.world.pos.y -= r * Math_SinS(xrot); - this->actor.world.pos.z += r * Math_CosS(xrot) * Math_CosS(yrot); + ArrowBomb_SetPosition(this, arrow); this->timer = 10; @@ -531,14 +538,7 @@ void ArrowBomb_Fly(EnBom* this, PlayState* play) { Actor_Kill(&this->actor); return; } - // copy position and rotation from arrow - this->actor.world.pos = arrow->actor.world.pos; - f32 r = 10.0f; - f32 xrot = arrow->actor.world.rot.x; - f32 yrot = arrow->actor.world.rot.y; - this->actor.world.pos.x += r * Math_SinS(yrot) * Math_CosS(xrot); - this->actor.world.pos.y -= r * Math_SinS(xrot); - this->actor.world.pos.z += r * Math_CosS(yrot) * Math_CosS(xrot); + ArrowBomb_SetPosition(this, arrow); distanceScaled = Math_Vec3f_DistXYZ(&this->unkPos, &this->actor.world.pos) * (1.0f / 24.0f); this->unk_158 = distanceScaled; 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 4d013642e40..9bd4e9922ff 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2558,6 +2558,9 @@ s32 func_808350A4(PlayState* play, Player* this) { if (!CVarGetInteger("gInfiniteAmmo", 0)) { play->shootingGalleryStatus--; } + } else if (item == ITEM_BOW && this->heldItemAction == PLAYER_IA_BOW_BOMB) { + Inventory_ChangeAmmo(ITEM_BOW, -1); + Inventory_ChangeAmmo(ITEM_BOMB, -1); } else { Inventory_ChangeAmmo(item, -1); } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index c38c3cd7496..8a16d240986 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -42,7 +42,6 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 130, 130, 130, pauseCtx->alpha); } else if ((item == ITEM_BOMB && AMMO(item) == CUR_CAPACITY(UPG_BOMB_BAG)) || (item == ITEM_BOW && AMMO(item) == CUR_CAPACITY(UPG_QUIVER)) || - (item == ITEM_BOW_ARROW_BOMB && MIN(AMMO(ITEM_BOW), AMMO(ITEM_BOMB)) == MIN(CUR_CAPACITY(UPG_QUIVER), CUR_CAPACITY(UPG_BOMB_BAG))) || (item == ITEM_SLINGSHOT && AMMO(item) == CUR_CAPACITY(UPG_BULLET_BAG)) || (item == ITEM_STICK && AMMO(item) == CUR_CAPACITY(UPG_STICKS)) || (item == ITEM_NUT && AMMO(item) == CUR_CAPACITY(UPG_NUTS)) || (item == ITEM_BOMBCHU && ammo == 50) || @@ -1033,7 +1032,11 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { uint16_t targetButtonIndex = pauseCtx->equipTargetCBtn + 1; for (uint16_t otherSlotIndex = 0; otherSlotIndex < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); otherSlotIndex++) { - if (gSaveContext.equips.buttonItems[targetButtonIndex] == ITEM_BOW && pauseCtx->equipTargetItem == ITEM_BOMB) { + int slot_item = gSaveContext.equips.buttonItems[targetButtonIndex]; + // Don't check for bomb arrows so you can replace bomb arrow equip with just bombs + if ((slot_item == ITEM_BOW || slot_item == ITEM_BOW_ARROW_FIRE || + slot_item == ITEM_BOW_ARROW_ICE || slot_item == ITEM_BOW_ARROW_LIGHT) + && pauseCtx->equipTargetItem == ITEM_BOMB) { pauseCtx->equipTargetItem = ITEM_BOW_ARROW_BOMB; pauseCtx->equipTargetSlot = SLOT_BOW; } From df01a29bfbf3550a09c96d22708a750c235d1224 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Thu, 14 Dec 2023 10:45:55 -0600 Subject: [PATCH 3/7] Bomb Arrows: Add enhancement checkbutton --- soh/soh/Enhancements/presets.h | 1 + soh/soh/SohMenuBar.cpp | 28 ++++++++++--------- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 7 +++-- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 22c9dd7db3d..29a8c428541 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -242,6 +242,7 @@ const std::vector enhancementsCvars = { "gAddTraps.Speed", "gAddTraps.Tele", "gAddTraps.Void", + "gBombArrows", }; const std::vector cheatCvars = { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 0c0a1240b5e..9900cd50bc9 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -391,7 +391,7 @@ void DrawSettingsMenu() { UIWidgets::Tooltip("Changes the scaling of the ImGui menu elements."); UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); - + static std::unordered_map windowBackendNames = { { LUS::WindowBackend::DX11, "DirectX" }, { LUS::WindowBackend::SDL_OPENGL, "OpenGL"}, @@ -468,9 +468,9 @@ void DrawSettingsMenu() { } ImGui::EndMenu(); } - + UIWidgets::Spacer(0); - + if (ImGui::BeginMenu("Accessibility")) { #if defined(_WIN32) || defined(__APPLE__) UIWidgets::PaddedEnhancementCheckbox("Text to Speech", "gA11yTTS"); @@ -478,7 +478,7 @@ void DrawSettingsMenu() { #endif UIWidgets::PaddedEnhancementCheckbox("Disable Idle Camera Re-Centering", "gA11yDisableIdleCam"); UIWidgets::Tooltip("Disables the automatic re-centering of the camera when idle."); - + ImGui::EndMenu(); } ImGui::EndMenu(); @@ -606,6 +606,8 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks"); UIWidgets::PaddedEnhancementCheckbox("Nuts explode bombs", "gNutsExplodeBombs", true, false); UIWidgets::Tooltip("Makes nuts explode bombs, similar to how they interact with bombchus. This does not affect bombflowers."); + UIWidgets::PaddedEnhancementCheckbox("Bomb Arrows", "gBombArrows", true, false); + UIWidgets::Tooltip("Equip bombs onto the same button as your bow to shoot arrows that explode on impact"); UIWidgets::PaddedEnhancementCheckbox("Equip Multiple Arrows at Once", "gSeparateArrows", true, false); UIWidgets::Tooltip("Allow the bow and magic arrows to be equipped at the same time on different slots. (Note this will disable the behaviour of the 'Equip Dupe' glitch)"); UIWidgets::PaddedEnhancementCheckbox("Bow as Child/Slingshot as Adult", "gBowSlingShotAmmoFix", true, false); @@ -878,7 +880,7 @@ void DrawEnhancementsMenu() { OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BLUE_FIRE_ARROWS); static const char* forceEnableBlueFireArrowsText = "This setting is forcefully enabled because a savefile\nwith \"Blue Fire Arrows\" is loaded."; - UIWidgets::PaddedEnhancementCheckbox("Blue Fire Arrows", "gBlueFireArrows", true, false, + UIWidgets::PaddedEnhancementCheckbox("Blue Fire Arrows", "gBlueFireArrows", true, false, forceEnableBlueFireArrows, forceEnableBlueFireArrowsText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Allows Ice Arrows to melt red ice.\nMay require a room reload if toggled during gameplay."); @@ -887,7 +889,7 @@ void DrawEnhancementsMenu() { OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SUNLIGHT_ARROWS); static const char* forceEnableSunLightArrowsText = "This setting is forcefully enabled because a savefile\nwith \"Sunlight Arrows\" is loaded."; - UIWidgets::PaddedEnhancementCheckbox("Sunlight Arrows", "gSunlightArrows", true, false, + UIWidgets::PaddedEnhancementCheckbox("Sunlight Arrows", "gSunlightArrows", true, false, forceEnableSunLightArrows, forceEnableSunLightArrowsText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Allows Light Arrows to activate sun switches.\nMay require a room reload if toggled during gameplay."); @@ -1062,8 +1064,8 @@ void DrawEnhancementsMenu() { "Fixes an incorrect calculation that acted like water underneath ground was above it."); UIWidgets::PaddedEnhancementCheckbox("Fix Bush Item Drops", "gBushDropFix", true, false); UIWidgets::Tooltip("Fixes the bushes to drop items correctly rather than spawning undefined items."); - UIWidgets::PaddedEnhancementCheckbox("Fix falling from vine edges", "gFixVineFall", true, false); - UIWidgets::Tooltip("Prevents immediately falling off climbable surfaces if climbing on the edges."); + UIWidgets::PaddedEnhancementCheckbox("Fix falling from vine edges", "gFixVineFall", true, false); + UIWidgets::Tooltip("Prevents immediately falling off climbable surfaces if climbing on the edges."); UIWidgets::PaddedEnhancementCheckbox("Fix Link's eyes open while sleeping", "gFixEyesOpenWhileSleeping", true, false); UIWidgets::Tooltip("Fixes Link's eyes being open in the opening cutscene when he is supposed to be sleeping."); UIWidgets::PaddedEnhancementCheckbox("Fix Darunia dancing too fast", "gEnhancements.FixDaruniaDanceSpeed", @@ -1396,12 +1398,12 @@ void DrawCheatsMenu() { if (ImGui::Button("Change Age")) { CVarSetInteger("gSwitchAge", 1); } - UIWidgets::Tooltip("Switches Link's age and reloads the area."); + UIWidgets::Tooltip("Switches Link's age and reloads the area."); if (ImGui::Button("Clear Cutscene Pointer")) { GameInteractor::RawAction::ClearCutscenePointer(); } - UIWidgets::Tooltip("Clears the cutscene pointer to a value safe for wrong warps."); + UIWidgets::Tooltip("Clears the cutscene pointer to a value safe for wrong warps."); ImGui::EndDisabled(); @@ -1581,12 +1583,12 @@ void DrawRandomizerMenu() { OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE || (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_VANILLA && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_OWN_DUNGEON && - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_STARTWITH) || + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_STARTWITH) || !IS_RANDO) { disableKeyColors = false; } - static const char* disableKeyColorsText = + static const char* disableKeyColorsText = "This setting is disabled because a savefile is loaded without any key\n" "shuffle settings set to \"Any Dungeon\", \"Overworld\" or \"Anywhere\""; @@ -1642,4 +1644,4 @@ void SohMenuBar::DrawElement() { ImGui::EndMenuBar(); } } -} // namespace SohGui +} // namespace SohGui diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 8a16d240986..071ea3423fa 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -1034,9 +1034,10 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { otherSlotIndex++) { int slot_item = gSaveContext.equips.buttonItems[targetButtonIndex]; // Don't check for bomb arrows so you can replace bomb arrow equip with just bombs - if ((slot_item == ITEM_BOW || slot_item == ITEM_BOW_ARROW_FIRE || - slot_item == ITEM_BOW_ARROW_ICE || slot_item == ITEM_BOW_ARROW_LIGHT) - && pauseCtx->equipTargetItem == ITEM_BOMB) { + if (CVarGetInteger("gBombArrows", 0) && + (slot_item == ITEM_BOW || slot_item == ITEM_BOW_ARROW_FIRE || + slot_item == ITEM_BOW_ARROW_ICE || slot_item == ITEM_BOW_ARROW_LIGHT) && + pauseCtx->equipTargetItem == ITEM_BOMB) { pauseCtx->equipTargetItem = ITEM_BOW_ARROW_BOMB; pauseCtx->equipTargetSlot = SLOT_BOW; } From e6d84e2ddeb242537963827e3ac8aec703e5c5e5 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Wed, 20 Dec 2023 23:50:10 -0600 Subject: [PATCH 4/7] Fix z_en_bom.h include capitalization --- soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c index db1f0fd13bb..f50448348ec 100644 --- a/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c +++ b/soh/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c @@ -5,7 +5,7 @@ */ #include "z_en_arrow.h" -#include "overlays/actors/ovl_en_bom/z_en_bom.h" +#include "overlays/actors/ovl_En_Bom/z_en_bom.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_gi_nuts/object_gi_nuts.h" From ed831a81528eef1c3d6a0cd1ea4130d7e5cc4554 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Thu, 21 Dec 2023 00:12:34 -0600 Subject: [PATCH 5/7] Duplicate function in z_en_bom.c to remove implicit declaration --- soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c index 7d53d7942fb..a34ca45ddd2 100644 --- a/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c +++ b/soh/src/overlays/actors/ovl_En_Bom/z_en_bom.c @@ -528,6 +528,12 @@ void ArrowBomb_Charge(EnBom* this, PlayState* play) { } } +void ArrowBomb_80865ECC(Vec3f* unkPos, Vec3f* firePos, f32 scale) { + unkPos->x += ((firePos->x - unkPos->x) * scale); + unkPos->y += ((firePos->y - unkPos->y) * scale); + unkPos->z += ((firePos->z - unkPos->z) * scale); +} + void ArrowBomb_Fly(EnBom* this, PlayState* play) { EnArrow* arrow; f32 distanceScaled; @@ -545,7 +551,7 @@ void ArrowBomb_Fly(EnBom* this, PlayState* play) { if (distanceScaled < 1.0f) { this->unk_158 = 1.0f; } - func_80865ECC(&this->unkPos, &this->actor.world.pos, 0.05f); + ArrowBomb_80865ECC(&this->unkPos, &this->actor.world.pos, 0.05f); if (arrow->hitFlags & 1) { this->timer = 0; From 0d0d59ffc02a26382618870837e98381974c64ea Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Thu, 21 Dec 2023 08:26:22 -0600 Subject: [PATCH 6/7] Fix broken messages --- soh/src/code/z_message_PAL.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 7bb3803fcc6..96660c34161 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -470,8 +470,8 @@ void Message_DrawTextboxIcon(PlayState* play, Gfx** p, s16 x, s16 y) { sIconEnvColors[1] = color; } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { sIconPrimColors[0] = (Color_RGB8){ 0, 200, 80 }; - sIconPrimColors[1] = (Color_RGB8){ 50, 255, 130 }; - sIconEnvColors[1] = (Color_RGB8){ 50, 255, 130 }; + sIconPrimColors[1] = (Color_RGB8){ 50, 255, 130 }; + sIconEnvColors[1] = (Color_RGB8){ 50, 255, 130 }; } static Color_RGB8 sIconPrim = { 0, 80, 200 }; static s16 sIconFlashTimer = 12; @@ -1132,6 +1132,9 @@ void Message_LoadItemIcon(PlayState* play, u16 itemId, s16 y) { interfaceCtx->mapPalette[30] = 0xFF; interfaceCtx->mapPalette[31] = 0xFF; } + if (itemId > ITEM_BOW_ARROW_BOMB) { + itemId += 1; + } if (itemId < ITEM_MEDALLION_FOREST) { R_TEXTBOX_ICON_XPOS = R_TEXT_INIT_XPOS - sIconItem32XOffsets[gSaveContext.language]; R_TEXTBOX_ICON_YPOS = y + 6; @@ -3139,7 +3142,7 @@ void Message_Update(PlayState* play) { if (msgCtx->msgLength == 0) { return; } - + GameInteractor_ExecuteOnDialogMessage(); bool isB_Held = CVarGetInteger("gSkipText", 0) != 0 ? CHECK_BTN_ALL(input->cur.button, BTN_B) && !sTextboxSkipped From 426efee8622a1809406d1560678f87f6459374e6 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Thu, 21 Dec 2023 09:06:22 -0600 Subject: [PATCH 7/7] Fix broken custom messages --- soh/soh/Enhancements/custom-message/CustomMessageManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index e552a9672d9..5309f7d6e41 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -105,7 +105,8 @@ void CustomMessage::Replace(std::string&& oldStr, std::string&& newEnglish, std: void CustomMessage::Format(ItemID iid) { for (std::string* str : { &english, &french, &german }) { - str->insert(0, ITEM_OBTAINED(iid)); + // HACK: this is so messed up + str->insert(0, ITEM_OBTAINED(iid > ITEM_BOW_ARROW_BOMB ? iid - 1 : iid)); size_t start_pos = 0; std::replace(str->begin(), str->end(), '&', NEWLINE()[0]); while ((start_pos = str->find('^', start_pos)) != std::string::npos) { @@ -253,7 +254,7 @@ bool CustomMessageManager::ClearMessageTable(std::string tableID) { return true; } -bool CustomMessageManager::AddCustomMessageTable(std::string tableID) { +bool CustomMessageManager::AddCustomMessageTable(std::string tableID) { CustomMessageTable newMessageTable; return messageTables.emplace(tableID, newMessageTable).second; }