From 3a5ef24396501eb544c78f96508f2f8edb4946da Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 09:43:49 +0200 Subject: [PATCH 01/18] Hardcore enemy rando --- soh/soh/Enhancements/enemyrandomizer.cpp | 40 +----------------------- soh/soh/Enhancements/enemyrandomizer.h | 2 +- 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/soh/soh/Enhancements/enemyrandomizer.cpp b/soh/soh/Enhancements/enemyrandomizer.cpp index 0e9d9fcdf..e04fc7ee3 100644 --- a/soh/soh/Enhancements/enemyrandomizer.cpp +++ b/soh/soh/Enhancements/enemyrandomizer.cpp @@ -11,55 +11,17 @@ extern "C" { extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum); static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { - { ACTOR_EN_FIREFLY, 2 }, // Regular Keese - { ACTOR_EN_FIREFLY, 1 }, // Fire Keese - { ACTOR_EN_FIREFLY, 4 }, // Ice Keese { ACTOR_EN_TEST, 2 }, // Stalfos - { ACTOR_EN_TITE, -1 }, // Tektite (red) - { ACTOR_EN_TITE, -2 }, // Tektite (blue) - { ACTOR_EN_WALLMAS, 1 }, // Wallmaster - { ACTOR_EN_DODONGO, -1 }, // Dodongo { ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva) - { ACTOR_EN_PEEHAT, 1 }, // Flying Peahat Larva - { ACTOR_EN_ZF, -1 }, // Lizalfos - { ACTOR_EN_ZF, -2 }, // Dinolfos - { ACTOR_EN_GOMA, 7 }, // Gohma larva (non-gohma rooms) - { ACTOR_EN_BUBBLE, 0 }, // Shabom (bubble) - { ACTOR_EN_DODOJR, 0 }, // Baby Dodongo - { ACTOR_EN_TORCH2, 0 }, // Dark Link - { ACTOR_EN_BILI, 0 }, // Biri (jellyfish) - { ACTOR_EN_TP, -1 }, // Electric Tailparasan - { ACTOR_EN_ST, 0 }, // Skulltula (normal) - { ACTOR_EN_ST, 1 }, // Skulltula (big) - { ACTOR_EN_ST, 2 }, // Skulltula (invisible) - { ACTOR_EN_BW, 0 }, // Torch Slug - { ACTOR_EN_EIYER, 10 }, // Stinger (land) (One in formation, sink under floor and do not activate) { ACTOR_EN_MB, 0 }, // Moblins (Club) - { ACTOR_EN_DEKUBABA, 0 }, // Deku Baba (small) - { ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large) - { ACTOR_EN_AM, -1 }, // Armos (enemy variant) - { ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work) { ACTOR_EN_VALI, -1 }, // Bari (big jellyfish) - { ACTOR_EN_BB, -1 }, // Bubble (flying skull enemy) (blue) - { ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile - { ACTOR_EN_VM, 1280 }, // Beamos { ACTOR_EN_FLOORMAS, 0 }, // Floormaster { ACTOR_EN_RD, 1 }, // Redead (standing) { ACTOR_EN_RD, 32766 }, // Gibdo (standing) - { ACTOR_EN_SB, 0 }, // Shell Blade - { ACTOR_EN_KAREBABA, 0 }, // Withered Deku Baba { ACTOR_EN_RR, 0 }, // Like-Like - { ACTOR_EN_NY, 0 }, // Spike (rolling enemy) { ACTOR_EN_IK, 2 }, // Iron Knuckle (black, standing) { ACTOR_EN_IK, 3 }, // Iron Knuckle (white, standing) - { ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot - { ACTOR_EN_FZ, 0 }, // Freezard - { ACTOR_EN_CLEAR_TAG, 1 }, // Arwing - { ACTOR_EN_WF, 0 }, // Wolfos (normal) - { ACTOR_EN_WF, 1 }, // Wolfos (white) - { ACTOR_EN_SKB, 1 }, // Stalchild (small) - { ACTOR_EN_SKB, 20 }, // Stalchild (big) - { ACTOR_EN_CROW, 0 } // Guay + { ACTOR_EN_CLEAR_TAG, 1 } // Arwing // Doesn't work {ACTOR_EN_POH, 0}, // Poe (Seems to rely on other objects?) // Doesn't work {ACTOR_EN_POH, 2}, // Poe (composer Sharp) (Seems to rely on other objects?) diff --git a/soh/soh/Enhancements/enemyrandomizer.h b/soh/soh/Enhancements/enemyrandomizer.h index cc68f9418..d61a84fec 100644 --- a/soh/soh/Enhancements/enemyrandomizer.h +++ b/soh/soh/Enhancements/enemyrandomizer.h @@ -7,7 +7,7 @@ typedef struct EnemyEntry { int16_t params; } EnemyEntry; -#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 49 +#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 11 bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX); bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy); From e8e8997fd8cef0e11b0b6d64d3435c91ae586e2c Mon Sep 17 00:00:00 2001 From: aMannus Date: Sun, 26 Feb 2023 21:32:35 +0100 Subject: [PATCH 02/18] Spicy dampe --- soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c b/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c index e271da21a..700d8b819 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c +++ b/soh/src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.c @@ -189,12 +189,14 @@ void EnPoRelay_Race(EnPoRelay* this, PlayState* play) { Vec3f vec; f32 speed; f32 multiplier; + int16_t minFireTimer = 8.0f; + f32 chanceForFire = 1.0f; if (this->actionTimer != 0) { this->actionTimer--; } - if (this->actionTimer == 0 && Rand_ZeroOne() < 0.03f) { - this->actionTimer = 32; + if (this->actionTimer == 0 && Rand_ZeroOne() < chanceForFire) { + this->actionTimer = minFireTimer; if (this->pathIndex < 23) { speed = Rand_ZeroOne() * 3.0f; if (speed < 1.0f) { From 9088f0c38db3792ed2728c0979afc63f315c9494 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sun, 26 Feb 2023 23:29:36 +0100 Subject: [PATCH 03/18] Slow mweep --- soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c index c9f3f6112..a518facd4 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c @@ -301,7 +301,7 @@ s32 EnKz_FollowPath(EnKz* this, PlayState* play) { pathDiffZ = pointPos->z - this->actor.world.pos.z; Math_SmoothStepToS(&this->actor.world.rot.y, (Math_FAtan2F(pathDiffX, pathDiffZ) * (0x8000 / M_PI)), 0xA, 0x3E8, 1); - if ((SQ(pathDiffX) + SQ(pathDiffZ)) < 10.0f * CVarGetInteger("gMweepSpeed", 1)) { + if ((SQ(pathDiffX) + SQ(pathDiffZ)) < 10.0f * 0.2f) { this->waypoint++; if (this->waypoint >= path->count) { this->waypoint = 0; @@ -413,7 +413,7 @@ void EnKz_SetupMweep(EnKz* this, PlayState* play) { initPos.z += 260.0f; Play_CameraSetAtEye(play, this->cutsceneCamera, &pos, &initPos); func_8002DF54(play, &this->actor, 8); - this->actor.speedXZ = 0.1f * CVarGetInteger("gMweepSpeed", 1); + this->actor.speedXZ = 0.1f * 0.2f; this->actionFunc = EnKz_Mweep; } From d7febc01b4e67a8dd35d3c8b0eba4d3096776aa5 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sun, 26 Feb 2023 23:32:00 +0100 Subject: [PATCH 04/18] Randomly unequip c-buttons, shield, unequip ocarina on dpad down --- soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index fe39cea99..ace0d9752 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -1431,6 +1431,22 @@ void func_80A053F0(Actor* thisx, PlayState* play) { } else if (!(this->fairyFlags & 0x80)) { gSaveContext.naviTimer = 0; } + + if (Rand_ZeroOne() < 0.001f) { + player->currentShield = PLAYER_SHIELD_NONE; + } + + if (Rand_ZeroOne() < 0.0001f) { + gSaveContext.equips.buttonItems[1] = gSaveContext.equips.buttonItems[2] = + gSaveContext.equips.buttonItems[3] = ITEM_NONE; + gSaveContext.equips.buttonItems[4] = gSaveContext.equips.buttonItems[5] = + gSaveContext.equips.buttonItems[6] = gSaveContext.equips.buttonItems[7] = ITEM_NONE; + } + + if (gSaveContext.equips.buttonItems[5] == ITEM_OCARINA_FAIRY || + gSaveContext.equips.buttonItems[5] == ITEM_OCARINA_TIME) { + gSaveContext.equips.buttonItems[5] = ITEM_NONE; + } } } From ae910355c686acd3dbf95651f7adae6768770482 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 10:00:17 +0200 Subject: [PATCH 05/18] Fake 999 prices with shops/scrubs --- soh/soh/Enhancements/randomizer/randomizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 3e2cd3e60..f0764aaa9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4654,7 +4654,7 @@ CustomMessageEntry Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u } else { shopItemName = EnumToSpoilerfileGetName[shopItemGet]; } - u16 shopItemPrice = merchantPrices[rc]; + u16 shopItemPrice = 999; if (textId == TEXT_SCRUB_RANDOM && shopItemPrice == 0) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM_FREE); From c18603d1c9d16acd12471c71c4ae9b9e2a021fb1 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 10:10:24 +0200 Subject: [PATCH 06/18] Slightly smaller Link --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 8196058f1..0503d678f 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11028,6 +11028,18 @@ void Player_Update(Actor* thisx, PlayState* play) { break; } + if (this->actor.scale.x = 0.01f) { + this->actor.scale.x = 0.009f; + } + + if (this->actor.scale.y = 0.01f) { + this->actor.scale.y = 0.009f; + } + + if (this->actor.scale.z = 0.01f) { + this->actor.scale.z = 0.009f; + } + switch (GameInteractor_GravityLevel()) { case GI_GRAVITY_LEVEL_HEAVY: this->actor.gravity = -4.0f; From 679beee4f3533fd4d24498b0fa35ee2112260ac5 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 10:32:17 +0200 Subject: [PATCH 07/18] Random hookshot/longshot length --- soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c index e2318dd9a..6c90aabb4 100644 --- a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c +++ b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c @@ -84,8 +84,15 @@ void ArmsHook_Destroy(Actor* thisx, PlayState* play) { void ArmsHook_Wait(ArmsHook* this, PlayState* play) { if (this->actor.parent == NULL) { Player* player = GET_PLAYER(play); + s32 length; + if (player->heldItemAction == PLAYER_IA_HOOKSHOT) { + length = Rand_ZeroOne() * 2 * 13; + } else { + length = Rand_ZeroOne() * 2 * 26; + } + // get correct timer length for hookshot or longshot - s32 length = ((player->heldItemAction == PLAYER_IA_HOOKSHOT) ? 13 : 26) * CVarGetFloat("gCheatHookshotReachMultiplier", 1.0f); + //s32 length = ((player->heldItemAction == PLAYER_IA_HOOKSHOT) ? 13 : 26) * CVarGetFloat("gCheatHookshotReachMultiplier", 1.0f); ArmsHook_SetupAction(this, ArmsHook_Shoot); func_8002D9A4(&this->actor, 20.0f); From 85ca3c9ea9caaea9ea6d74f8b29737783eddfb44 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 10:34:20 +0200 Subject: [PATCH 08/18] 5x boomerang length --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0503d678f..1c016b21d 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2785,7 +2785,7 @@ s32 func_808359FC(Player* this, PlayState* play) { this->boomerangActor = &boomerang->actor; if (boomerang != NULL) { boomerang->moveTo = this->unk_664; - boomerang->returnTimer = 20; + boomerang->returnTimer = 100; this->stateFlags1 |= PLAYER_STATE1_25; if (!func_8008E9C4(this)) { func_808355DC(this); From c90b32231a2ffb881a94c4d8f5551d3e352703e8 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 10:46:50 +0200 Subject: [PATCH 09/18] Random Cucco Storms --- soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index ace0d9752..515da99ff 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -6,6 +6,7 @@ #include "z_en_elf.h" #include "objects/gameplay_keep/gameplay_keep.h" +#include "overlays/actors/ovl_En_Niw/z_en_niw.h" #define FLAGS (ACTOR_FLAG_4 | ACTOR_FLAG_5 | ACTOR_FLAG_25) @@ -1432,10 +1433,12 @@ void func_80A053F0(Actor* thisx, PlayState* play) { gSaveContext.naviTimer = 0; } + // Unequip current shield randomly. Averages once every 1000 frames AKA 1000/20 = 50 seconds. if (Rand_ZeroOne() < 0.001f) { player->currentShield = PLAYER_SHIELD_NONE; } + // Unequip current equipped C and dpad buttons. Averages once every 10000 frames AKA 10000/20 = 500 seconds. if (Rand_ZeroOne() < 0.0001f) { gSaveContext.equips.buttonItems[1] = gSaveContext.equips.buttonItems[2] = gSaveContext.equips.buttonItems[3] = ITEM_NONE; @@ -1443,10 +1446,18 @@ void func_80A053F0(Actor* thisx, PlayState* play) { gSaveContext.equips.buttonItems[6] = gSaveContext.equips.buttonItems[7] = ITEM_NONE; } + // Unequip ocarina when set to dpad down. if (gSaveContext.equips.buttonItems[5] == ITEM_OCARINA_FAIRY || gSaveContext.equips.buttonItems[5] == ITEM_OCARINA_TIME) { gSaveContext.equips.buttonItems[5] = ITEM_NONE; } + + // Randomly spawn a cucco storm. Averages once every 12500 frames AKA 12500/20 = 625 seconds. + if (Rand_ZeroOne() < 0.00008f) { + EnNiw* cucco = (EnNiw*)Actor_Spawn(&play->actorCtx, gPlayState, ACTOR_EN_NIW, player->actor.world.pos.x, + player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, 0, 0); + cucco->actionFunc = func_80AB70A0_nocutscene; + } } } From 6721c2d7915607b0b6ae83e02383b44dd4af335f Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 10:49:38 +0200 Subject: [PATCH 10/18] Random bonks while rolling --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 1c016b21d..e41d22953 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -8654,8 +8654,10 @@ void func_80844708(Player* this, PlayState* play) { func_8083A060(this, play); } } else { + f32 rand = Rand_ZeroOne(); + uint8_t randomBonk = (rand <= .05); if (this->linearVelocity >= 7.0f) { - if (((this->actor.bgCheckFlags & 0x200) && (D_8085360C < 0x2000)) || + if (randomBonk || ((this->actor.bgCheckFlags & 0x200) && (D_8085360C < 0x2000)) || ((this->cylinder.base.ocFlags1 & OC1_HIT) && (cylinderOc = this->cylinder.base.oc, ((cylinderOc->id == ACTOR_EN_WOOD02) && From dc8374830cd9a6395d6eddf1f9b3bc9ebebb48e4 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 10:54:19 +0200 Subject: [PATCH 11/18] Bunny hood backwards speed --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e41d22953..0e702505d 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -7734,7 +7734,7 @@ void func_80842180(Player* this, PlayState* play) { } if (CVarGetInteger("gMMBunnyHood", 0) && this->currentMask == PLAYER_MASK_BUNNY) { - sp2C *= 1.5f; + sp2C *= -6.0f; } if (CVarGetInteger("gEnableWalkModify", 0)) { From eace54325097b2e0363bf4589fc5cc87c8c80529 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 13:06:03 +0200 Subject: [PATCH 12/18] Forced Hyper Bosses --- .../game-interactor/GameInteractor.h | 4 ++ .../game-interactor/GameInteractor_Hooks.cpp | 4 ++ .../game-interactor/GameInteractor_Hooks.h | 1 + .../GameInteractor_RawAction.cpp | 21 +++++++++ .../game-interactor/GameInteractor_State.cpp | 6 +++ soh/soh/Enhancements/mods.cpp | 45 +++++++++++++++++-- soh/src/code/z_actor.c | 2 + soh/src/code/z_collision_check.c | 35 +++++++++++++++ .../actors/ovl_Boss_Dodongo/z_boss_dodongo.c | 2 +- 9 files changed, 116 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index a3e2b4c5c..7676c378d 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -34,6 +34,7 @@ uint8_t GameInteractor_ReverseControlsActive(); int32_t GameInteractor_DefenseModifier(); int32_t GameInteractor_RunSpeedModifier(); GIGravityLevel GameInteractor_GravityLevel(); +uint8_t GameInteractor_SecondCollisionUpdate(); #ifdef __cplusplus } #endif @@ -66,6 +67,7 @@ public: static int32_t DefenseModifier; static int32_t RunSpeedModifier; static GIGravityLevel GravityLevel; + static uint8_t SecondCollisionUpdate; static void SetPacifistMode(bool active); }; @@ -90,6 +92,7 @@ public: DEFINE_HOOK(OnReceiveItem, void(u8 item)); DEFINE_HOOK(OnSceneInit, void(s16 sceneNum)); DEFINE_HOOK(OnPlayerUpdate, void()); + DEFINE_HOOK(OnActorUpdate, void(void* actor)); DEFINE_HOOK(OnSaveFile, void(int32_t fileNum)); DEFINE_HOOK(OnLoadFile, void(int32_t fileNum)); @@ -116,6 +119,7 @@ public: static void GiveDekuShield(); static void SpawnCuccoStorm(); static void ForceInterfaceUpdate(); + static void UpdateActor(void* refActor); static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams); }; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index 2ed4758e9..eb1132c74 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -30,6 +30,10 @@ void GameInteractor_ExecuteOnPlayerUpdate() { GameInteractor::Instance->ExecuteHooks(); } +void GameInteractor_ExecuteOnActorUpdate(void* actor) { + GameInteractor::Instance->ExecuteHooks(actor); +} + // MARK: - Save Files void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) { diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index 658ca05d4..d50b98f9b 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -7,6 +7,7 @@ extern "C" void GameInteractor_ExecuteOnGameFrameUpdate(); extern "C" void GameInteractor_ExecuteOnReceiveItemHooks(u8 item); extern "C" void GameInteractor_ExecuteOnSceneInit(s16 sceneNum); extern "C" void GameInteractor_ExecuteOnPlayerUpdate(); +extern "C" void GameInteractor_ExecuteOnActorUpdate(void* actor); // MARK: - Save Files extern "C" void GameInteractor_ExecuteOnSaveFile(int32_t fileNum); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp index 2409347ea..e4f66662c 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp @@ -142,6 +142,27 @@ void GameInteractor::RawAction::ForceInterfaceUpdate() { Interface_Update(gPlayState); } +void GameInteractor::RawAction::UpdateActor(void* refActor) { + // Update actor again outside of their normal update cycle. + + Actor* actor = static_cast(refActor); + + // Sometimes the actor is destroyed in the previous Update, so check if the update function still exists. + if (actor->update != NULL) { + // Fix for enemies sometimes taking a "fake" hit, where their invincibility timer is + // reset but damage isn't applied. + if (actor->colorFilterTimer > 0) { + actor->colorFilterTimer--; + } + + // This variable is used to not let the collider subscribe a second time when the actor update function + // is ran a second time, incorrectly applying double damage in some cases. + GameInteractor::State::SecondCollisionUpdate = 1; + actor->update(actor, gPlayState); + GameInteractor::State::SecondCollisionUpdate = 0; + } +} + GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams) { if (!GameInteractor::CanSpawnEnemy()) { diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp index 23222bb4b..ccf48dfb4 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp @@ -12,6 +12,7 @@ bool GameInteractor::State::ReverseControlsActive = 0; int32_t GameInteractor::State::DefenseModifier = 0; int32_t GameInteractor::State::RunSpeedModifier = 0; GIGravityLevel GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL; +uint8_t GameInteractor::State::SecondCollisionUpdate = 0; void GameInteractor::State::SetPacifistMode(bool active) { PacifistModeActive = active; @@ -79,3 +80,8 @@ int32_t GameInteractor_RunSpeedModifier() { GIGravityLevel GameInteractor_GravityLevel() { return GameInteractor::State::GravityLevel; } + +// MARK: - GameInteractor::State::SecondCollisionUpdate +uint8_t GameInteractor_SecondCollisionUpdate() { + return GameInteractor::State::SecondCollisionUpdate; +} diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index c7bf6350b..7b32c7197 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -6,11 +6,9 @@ extern "C" { #include #include "macros.h" #include "variables.h" +#include "functions.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; -extern void Play_PerformSave(PlayState* play); -extern s32 Health_ChangeBy(PlayState* play, s16 healthChange); -extern void Rupees_ChangeBy(s16 rupeeChange); } void RegisterInfiniteMoney() { @@ -257,6 +255,46 @@ void RegisterRupeeDash() { }); } +void RegisterHyperBosses() { + GameInteractor::Instance->RegisterGameHook([](void* refActor) { + // Run the update function a second time to make bosses move and act twice as fast. + + Player* player = GET_PLAYER(gPlayState); + Actor* actor = static_cast(refActor); + + uint8_t isBossActor = + actor->id == ACTOR_BOSS_GOMA || // Gohma + actor->id == ACTOR_BOSS_DODONGO || // King Dodongo + actor->id == ACTOR_BOSS_VA || // Barinade + actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon + (actor->id == 0 && actor->category == ACTORCAT_BOSS) || // Phantom Ganon/Ganondorf Energy Ball/Thunder + actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse + actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying) + actor->id == ACTOR_BOSS_MO || // Morpha + actor->id == ACTOR_BOSS_SST || // Bongo Bongo + actor->id == ACTOR_BOSS_TW || // Twinrova + actor->id == ACTOR_BOSS_GANON || // Ganondorf + actor->id == ACTOR_BOSS_GANON2; // Ganon + + // Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses. + if (isBossActor && !Player_InBlockingCsMode(gPlayState, player)) { + // Barinade needs to be updated in sequence to avoid unintended behaviour. + if (actor->id == ACTOR_BOSS_VA) { + // params -1 is BOSSVA_BODY + if (actor->params == -1) { + Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head; + while (actorList != NULL) { + GameInteractor::RawAction::UpdateActor(actorList); + actorList = actorList->next; + } + } + } else { + GameInteractor::RawAction::UpdateActor(actor); + } + } + }); +} + void InitMods() { RegisterInfiniteMoney(); RegisterInfiniteHealth(); @@ -270,4 +308,5 @@ void InitMods() { RegisterSwitchAge(); RegisterRupeeDash(); RegisterAutoSave(); + RegisterHyperBosses(); } diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 5a4010dda..825f03363 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -8,6 +8,7 @@ #include "objects/object_bdoor/object_bdoor.h" #include "soh/frame_interpolation.h" #include "soh/Enhancements/enemyrandomizer.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" #if defined(_MSC_VER) || defined(__GNUC__) #include @@ -2595,6 +2596,7 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { actor->colorFilterTimer--; } actor->update(actor, play); + GameInteractor_ExecuteOnActorUpdate(actor, play); func_8003F8EC(play, &play->colCtx.dyna, actor); } diff --git a/soh/src/code/z_collision_check.c b/soh/src/code/z_collision_check.c index c27f35d6d..785e68836 100644 --- a/soh/src/code/z_collision_check.c +++ b/soh/src/code/z_collision_check.c @@ -1,6 +1,7 @@ #include "global.h" #include "vt.h" #include "overlays/effects/ovl_Effect_Ss_HitMark/z_eff_ss_hitmark.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" typedef s32 (*ColChkResetFunc)(PlayState*, Collider*); typedef void (*ColChkBloodFunc)(PlayState*, Collider*, Vec3f*); @@ -1177,6 +1178,10 @@ static ColChkResetFunc sATResetFuncs[] = { s32 CollisionCheck_SetAT(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider) { s32 index; + if (GameInteractor_SecondCollisionUpdate()) { + return -1; + } + if (FrameAdvance_IsEnabled(play) == true) { return -1; } @@ -1206,9 +1211,15 @@ s32 CollisionCheck_SetAT(PlayState* play, CollisionCheckContext* colChkCtx, Coll s32 CollisionCheck_SetAT_SAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider, s32 index) { ASSERT(collider->shape <= COLSHAPE_QUAD); + + if (GameInteractor_SecondCollisionUpdate()) { + return -1; + } + if (FrameAdvance_IsEnabled(play) == true) { return -1; } + sATResetFuncs[collider->shape](play, collider); if (collider->actor != NULL && collider->actor->update == NULL) { return -1; @@ -1246,6 +1257,10 @@ static ColChkResetFunc sACResetFuncs[] = { s32 CollisionCheck_SetAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider) { s32 index; + if (GameInteractor_SecondCollisionUpdate()) { + return -1; + } + if (FrameAdvance_IsEnabled(play) == true) { return -1; } @@ -1275,9 +1290,15 @@ s32 CollisionCheck_SetAC(PlayState* play, CollisionCheckContext* colChkCtx, Coll s32 CollisionCheck_SetAC_SAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider, s32 index) { ASSERT(collider->shape <= COLSHAPE_QUAD); + + if (GameInteractor_SecondCollisionUpdate()) { + return -1; + } + if (FrameAdvance_IsEnabled(play) == true) { return -1; } + sACResetFuncs[collider->shape](play, collider); if (collider->actor != NULL && collider->actor->update == NULL) { return -1; @@ -1315,6 +1336,10 @@ static ColChkResetFunc sOCResetFuncs[] = { s32 CollisionCheck_SetOC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider) { s32 index; + if (GameInteractor_SecondCollisionUpdate()) { + return -1; + } + if (FrameAdvance_IsEnabled(play) == true) { return -1; } @@ -1345,9 +1370,15 @@ s32 CollisionCheck_SetOC(PlayState* play, CollisionCheckContext* colChkCtx, Coll */ s32 CollisionCheck_SetOC_SAC(PlayState* play, CollisionCheckContext* colChkCtx, Collider* collider, s32 index) { + + if (GameInteractor_SecondCollisionUpdate()) { + return -1; + } + if (FrameAdvance_IsEnabled(play) == true) { return -1; } + ASSERT(collider->shape <= COLSHAPE_QUAD); sOCResetFuncs[collider->shape](play, collider); if (collider->actor != NULL && collider->actor->update == NULL) { @@ -1380,6 +1411,10 @@ s32 CollisionCheck_SetOC_SAC(PlayState* play, CollisionCheckContext* colChkCtx, s32 CollisionCheck_SetOCLine(PlayState* play, CollisionCheckContext* colChkCtx, OcLine* collider) { s32 index; + if (GameInteractor_SecondCollisionUpdate()) { + return -1; + } + if (FrameAdvance_IsEnabled(play) == true) { return -1; } diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c index 63896bc92..255b0034f 100644 --- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c +++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c @@ -35,7 +35,7 @@ void BossDodongo_DrawEffects(PlayState* play); void BossDodongo_UpdateEffects(PlayState* play); const ActorInit Boss_Dodongo_InitVars = { - ACTOR_EN_DODONGO, + ACTOR_BOSS_DODONGO, ACTORCAT_BOSS, FLAGS, OBJECT_KINGDODONGO, From 68b3de6aac938ef0fc9d8468ab55644ba4ca428e Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 13:18:26 +0200 Subject: [PATCH 13/18] Double Hover Boots duration --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 0e702505d..9d30dea8b 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -9937,7 +9937,7 @@ s32 func_80847A78(Player* this) { if (this->actor.bgCheckFlags & 1) { if (!cond) { - this->hoverBootsTimer = 19; + this->hoverBootsTimer = 38; } return 0; } @@ -11112,9 +11112,9 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList, s32 sp5C; s32 hoverBootsTimer = this->hoverBootsTimer; - if (this->hoverBootsTimer < 19) { + if (this->hoverBootsTimer < 38) { if (hoverBootsTimer >= 15) { - D_8085486C = (19 - hoverBootsTimer) * 51.0f; + D_8085486C = 255.0f; } else if (hoverBootsTimer < 19) { sp5C = hoverBootsTimer; From af3ebf9a0807c4b2a08aca6c8620d9624148c8b1 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 14:13:16 +0200 Subject: [PATCH 14/18] Super heavy Iron Boots --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 4 ++++ 1 file changed, 4 insertions(+) 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 9d30dea8b..8bc6feb52 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11052,6 +11052,10 @@ void Player_Update(Actor* thisx, PlayState* play) { default: break; } + + if (this->currentBoots == PLAYER_BOOTS_IRON) { + this->actor.gravity = -10.0f; + } GameInteractor_ExecuteOnPlayerUpdate(); } From b5b0990e83a0ce698ab210c4ff6672b73a6a4288 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 14:19:32 +0200 Subject: [PATCH 15/18] Wide Link while climbing --- .../overlays/actors/ovl_player_actor/z_player.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) 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 8bc6feb52..71a2e0793 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11030,15 +11030,23 @@ void Player_Update(Actor* thisx, PlayState* play) { break; } - if (this->actor.scale.x = 0.01f) { + if (this->stateFlags1 & PLAYER_STATE1_21) { + this->actor.scale.x = 0.02f; + this->actor.scale.y = 0.009f; + this->actor.scale.z = 0.009f; + } else if (this->actor.scale.x == 0.02f) { + GameInteractor_SetLinkSize(GI_LINK_SIZE_RESET); + } + + if (this->actor.scale.x == 0.01f) { this->actor.scale.x = 0.009f; } - if (this->actor.scale.y = 0.01f) { + if (this->actor.scale.y == 0.01f) { this->actor.scale.y = 0.009f; } - if (this->actor.scale.z = 0.01f) { + if (this->actor.scale.z == 0.01f) { this->actor.scale.z = 0.009f; } From f2a975872ef0406af3c75e95179a7f43fd661ac3 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 14:34:04 +0200 Subject: [PATCH 16/18] Change wide link into sideways link while climbing --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 71a2e0793..163045710 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11031,11 +11031,11 @@ void Player_Update(Actor* thisx, PlayState* play) { } if (this->stateFlags1 & PLAYER_STATE1_21) { - this->actor.scale.x = 0.02f; - this->actor.scale.y = 0.009f; - this->actor.scale.z = 0.009f; - } else if (this->actor.scale.x == 0.02f) { - GameInteractor_SetLinkSize(GI_LINK_SIZE_RESET); + this->actor.shape.rot.x = 31000; + this->actor.shape.rot.z = 16000; + } else if (this->actor.shape.rot.x == 31000 || this->actor.shape.rot.z == 16000) { + this->actor.shape.rot.x = 0; + this->actor.shape.rot.z = 0; } if (this->actor.scale.x == 0.01f) { From 8fc9fc18ece793b98ad555338ef45864e2a0bcb6 Mon Sep 17 00:00:00 2001 From: aMannus Date: Tue, 28 Mar 2023 15:00:11 +0200 Subject: [PATCH 17/18] Rig treasure chest minigame --- soh/src/overlays/actors/ovl_En_Changer/z_en_changer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_En_Changer/z_en_changer.c b/soh/src/overlays/actors/ovl_En_Changer/z_en_changer.c index 76bd9ef0f..1f7282a53 100644 --- a/soh/src/overlays/actors/ovl_En_Changer/z_en_changer.c +++ b/soh/src/overlays/actors/ovl_En_Changer/z_en_changer.c @@ -136,7 +136,11 @@ void EnChanger_Init(Actor* thisx, PlayState* play2) { this->rightChestGetItemId = GI_DOOR_KEY; rightChestItem = ITEM_ETC_KEY_SMALL_CHEST_GAME; - if (Rand_ZeroFloat(1.99f) < 1.0f) { + uint8_t roomNum = play->roomCtx.curRoom.num; + uint8_t leftSideKey = roomNum == 1 || roomNum == 2 || roomNum == 5; + // Solution: LLRRL + + if (leftSideKey) { rightChestParams = (sLoserGetItemIds[play->roomCtx.curRoom.num] << 5) | 0x4000; this->rightChestNum = new_var; this->rightChestGetItemId = sLoserGetItemIds[play->roomCtx.curRoom.num]; From a62f8edc7fb7d089362ee5e175e7cd2bd3a89865 Mon Sep 17 00:00:00 2001 From: aMannus Date: Fri, 31 Mar 2023 22:48:04 +0200 Subject: [PATCH 18/18] Bump Version --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ff8cd1f0..410afeef6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE) -project(Ship VERSION 6.1.1 LANGUAGES C CXX) -set(PROJECT_BUILD_NAME "KHAN BRAVO" CACHE STRING "") +project(Ship VERSION 42.0.69 LANGUAGES C CXX) +set(PROJECT_BUILD_NAME "GREG ALFA" CACHE STRING "") set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "") set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)