From 7a79c2d9fb1a6c0be7423799e9755ab9e7895e86 Mon Sep 17 00:00:00 2001 From: Fredomato Date: Mon, 2 Dec 2024 00:54:59 +0000 Subject: [PATCH 1/4] Location spawn / random location --- soh/soh/Enhancements/mods.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 0a03beba08d..43678237fef 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1406,14 +1406,23 @@ void RegisterHeartSpawner() { Player* player = GET_PLAYER(gPlayState); - Vec3f_ positional = player->actor.world.pos; - positional.y = player->actor.world.pos.y + 100.0f; // Change the 100.0f to make its start spawn higher - EnItem00* actor = Item_DropCollectible(gPlayState, &positional, ITEM00_HEART_PIECE); // Change this to be your spawned item + Vec3f pos; + pos.y = 100.0f; + if (GET_PLAYER(gPlayState) != nullptr) { + pos.x = GET_PLAYER(gPlayState)->actor.world.pos.x; + pos.z = GET_PLAYER(gPlayState)->actor.world.pos.z; + } else { + pos.x = 0; + pos.z = 0; + } + // X/Z anywhere from -100.0 to +100.0 from player + pos.x += (float)(Random(0, 200)) - 100.0f; + pos.z += (float)(Random(0, 200)) - 100.0f; + + EnItem00* actor = Item_DropCollectible(gPlayState, &pos, ITEM00_HEART_PIECE); // Change this to be your spawned item actor->actor.speedXZ = Rand_CenteredFloat(5.0f) + 8.0f; // Speed it spawns at, higher = farther from link } - - void InitMods() { BossRush_RegisterHooks(); RandomizerRegisterHooks(); From 12e37011bd50b4471d99182a146ba83cffa6f69f Mon Sep 17 00:00:00 2001 From: Fredomato Date: Mon, 2 Dec 2024 02:51:45 +0000 Subject: [PATCH 2/4] HurtMagnet prototype (heart pieces / heart containers) complete --- soh/soh/Enhancements/mods.cpp | 86 ++++++++++++++++--- soh/soh/Network/CrowdControl/CrowdControl.cpp | 4 +- 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 43678237fef..45ad49c661b 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -55,6 +55,13 @@ extern PlayState* gPlayState; extern void Overlay_DisplayText(float duration, const char* text); } +std::set actorData = {}; +std::vector> actorDefaultData = {}; + +std::vector actorCatList = { + ACTORCAT_MISC +}; + // GreyScaleEndDlist #define dgEndGrayscaleAndEndDlistDL "__OTR__helpers/cosmetics/gEndGrayscaleAndEndDlistDL" static const ALIGN_ASSET(2) char gEndGrayscaleAndEndDlistDL[] = dgEndGrayscaleAndEndDlistDL; @@ -1408,19 +1415,77 @@ void RegisterHeartSpawner() { Vec3f pos; pos.y = 100.0f; - if (GET_PLAYER(gPlayState) != nullptr) { - pos.x = GET_PLAYER(gPlayState)->actor.world.pos.x; - pos.z = GET_PLAYER(gPlayState)->actor.world.pos.z; - } else { - pos.x = 0; - pos.z = 0; - } - // X/Z anywhere from -100.0 to +100.0 from player - pos.x += (float)(Random(0, 200)) - 100.0f; - pos.z += (float)(Random(0, 200)) - 100.0f; + if (GET_PLAYER(gPlayState) != nullptr) { + pos.x = GET_PLAYER(gPlayState)->actor.world.pos.x; + pos.z = GET_PLAYER(gPlayState)->actor.world.pos.z; + } else { + pos.x = 0; + pos.z = 0; + } + // X/Z anywhere from -100.0 to +100.0 from player + pos.x += (float)(Random(0, 200)) - 100.0f; + pos.z += (float)(Random(0, 200)) - 100.0f; EnItem00* actor = Item_DropCollectible(gPlayState, &pos, ITEM00_HEART_PIECE); // Change this to be your spawned item actor->actor.speedXZ = Rand_CenteredFloat(5.0f) + 8.0f; // Speed it spawns at, higher = farther from link + actorData.insert(&actor->actor); +} + +void ChaosEventActorMagnet() { + if (!gPlayState) { + return; + } + actorData.clear(); + actorDefaultData.clear(); + for (int i = 0; i < actorCatList.size(); i++) { + ActorListEntry currList = gPlayState->actorCtx.actorLists[actorCatList[i]]; + Actor* currAct = currList.head; + if (currAct != nullptr) { + while (currAct != nullptr) { + actorData.insert(currAct); + actorDefaultData.push_back({ currAct->world.pos, currAct->world.rot }); + currAct = currAct->next; + } + } + } +} + +void ChaosEventsRepeater() { + GameInteractor::Instance->RegisterGameHook([](void* actorRef) { + actorData.erase((Actor*)actorRef); + }); + + GameInteractor::Instance->RegisterGameHook( + [](void* actorRef) { Actor* actor = (Actor*)actorRef; + if (actor->id == ACTOR_EN_ITEM00 && (actor->params == ITEM00_HEART_PIECE || (actor->params == ITEM00_SOH_DUMMY))) { + EnItem00* item00 = (EnItem00*)actor; + if (actor->params != ITEM00_SOH_DUMMY || item00->itemEntry.getItemId == GI_HEART_PIECE || + item00->itemEntry.getItemId == GI_HEART_CONTAINER || + item00->itemEntry.getItemId == GI_HEART_CONTAINER_2) { + actorData.insert(actor); + } + } + }); + + GameInteractor::Instance->RegisterGameHook( + [](int16_t SceneNum) { actorData.clear(); + }); + + GameInteractor::Instance->RegisterGameHook([]() { + + if (!gPlayState || GameInteractor::IsGameplayPaused()) { + return; + } + + Player* player = GET_PLAYER(gPlayState); + + for (auto& actorUpdate : actorData) { + Math_SmoothStepToF(&actorUpdate->world.pos.x, player->actor.world.pos.x + 0, 0.4f, 5.0f, 0.0f); + Math_SmoothStepToF(&actorUpdate->world.pos.y, player->actor.world.pos.y, 0.4f, 5.0f, 0.0f); + Math_SmoothStepToF(&actorUpdate->world.pos.z, player->actor.world.pos.z + 0, 0.4f, 5.0f, 0.0f); + actorUpdate->world.rot = player->actor.world.rot; + } + }); } void InitMods() { @@ -1467,4 +1532,5 @@ void InitMods() { RegisterPauseMenuHooks(); RandoKaleido_RegisterHooks(); RegisterHeartSpawner(); + ChaosEventsRepeater(); } diff --git a/soh/soh/Network/CrowdControl/CrowdControl.cpp b/soh/soh/Network/CrowdControl/CrowdControl.cpp index bc8055140dd..84f15bc2f99 100644 --- a/soh/soh/Network/CrowdControl/CrowdControl.cpp +++ b/soh/soh/Network/CrowdControl/CrowdControl.cpp @@ -9,6 +9,7 @@ #include #include #include "soh/OTRGlobals.h" +#include "soh/enhancements/mods.h" extern "C" { #include @@ -390,8 +391,9 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { // Give Items and Consumables case kEffectAddHeartContainer: + RegisterHeartSpawner(); effect->giEffect = new GameInteractionEffect::ModifyHeartContainers(); - dynamic_cast(effect->giEffect)->parameters[0] = 1; + //dynamic_cast(effect->giEffect)->parameters[0] = 1; break; case kEffectFillMagic: effect->giEffect = new GameInteractionEffect::FillMagic(); From 6aa1a9d296fb81ede9317a816df43911ad2978a2 Mon Sep 17 00:00:00 2001 From: Fredomato Date: Mon, 2 Dec 2024 15:11:14 +0000 Subject: [PATCH 3/4] Added SFX and tweaked spawn location. --- soh/soh/Enhancements/mods.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 45ad49c661b..5ffcb1d7eb9 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1411,10 +1411,11 @@ void RegisterHeartSpawner() { return; } + int randHeartSpawn; Player* player = GET_PLAYER(gPlayState); Vec3f pos; - pos.y = 100.0f; + pos.y = 10.0f; if (GET_PLAYER(gPlayState) != nullptr) { pos.x = GET_PLAYER(gPlayState)->actor.world.pos.x; pos.z = GET_PLAYER(gPlayState)->actor.world.pos.z; @@ -1422,13 +1423,32 @@ void RegisterHeartSpawner() { pos.x = 0; pos.z = 0; } - // X/Z anywhere from -100.0 to +100.0 from player - pos.x += (float)(Random(0, 200)) - 100.0f; - pos.z += (float)(Random(0, 200)) - 100.0f; + // X/Z anywhere from 100.0 to 500.0 from player + pos.x += (float)(Random(100, 500)); + pos.z += (float)(Random(100, 500)); + + //randHeartSpawn = Random(0, 1); EnItem00* actor = Item_DropCollectible(gPlayState, &pos, ITEM00_HEART_PIECE); // Change this to be your spawned item actor->actor.speedXZ = Rand_CenteredFloat(5.0f) + 8.0f; // Speed it spawns at, higher = farther from link actorData.insert(&actor->actor); + Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + + //if (randHeartSpawn == 0) { + // EnItem00* actor = + // Item_DropCollectible(gPlayState, &pos, ITEM00_HEART_PIECE); // Change this to be your spawned item + // actor->actor.speedXZ = Rand_CenteredFloat(5.0f) + 8.0f; // Speed it spawns at, higher = farther from link + // actorData.insert(&actor->actor); + //} + + //else { + // EnItem00* actor = + // Item_DropCollectible(gPlayState, &pos, ITEM00_HEART_CONTAINER); // Change this to be your spawned item + // actor->actor.speedXZ = Rand_CenteredFloat(5.0f) + 8.0f; // Speed it spawns at, higher = farther from link + // actorData.insert(&actor->actor); + //} + } void ChaosEventActorMagnet() { From 10440b62a35bf1f3ead789c6b7c714f88957fb05 Mon Sep 17 00:00:00 2001 From: Fredomato Date: Wed, 4 Dec 2024 03:28:19 +0000 Subject: [PATCH 4/4] Changed functionality to interact with Sail --- .../Enhancements/game-interactor/GameInteractor_RawAction.cpp | 4 +++- soh/soh/Enhancements/mods.cpp | 4 ++-- soh/soh/Network/CrowdControl/CrowdControl.cpp | 3 +-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp index 24e38d9b4ae..a823c595680 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp @@ -4,6 +4,7 @@ #include "soh/Enhancements/randomizer/3drando/random.hpp" #include #include "soh/Enhancements/debugger/colViewer.h" +#include "soh/Enhancements/mods.h" extern "C" { #include "variables.h" @@ -17,7 +18,8 @@ extern PlayState* gPlayState; #include "overlays/actors/ovl_En_Bom/z_en_bom.h" void GameInteractor::RawAction::AddOrRemoveHealthContainers(int16_t amount) { - gSaveContext.healthCapacity += amount * 0x10; + RegisterHeartSpawner(); + //gSaveContext.healthCapacity += amount * 0x10; } void GameInteractor::RawAction::AddOrRemoveMagic(int8_t amount) { diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 5ffcb1d7eb9..ca4d697c2bb 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1429,10 +1429,10 @@ void RegisterHeartSpawner() { //randHeartSpawn = Random(0, 1); - EnItem00* actor = Item_DropCollectible(gPlayState, &pos, ITEM00_HEART_PIECE); // Change this to be your spawned item + EnItem00* actor = Item_DropCollectible2(gPlayState, &pos, ITEM00_HEART_PIECE); // Change this to be your spawned item actor->actor.speedXZ = Rand_CenteredFloat(5.0f) + 8.0f; // Speed it spawns at, higher = farther from link actorData.insert(&actor->actor); - Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &actor->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); //if (randHeartSpawn == 0) { diff --git a/soh/soh/Network/CrowdControl/CrowdControl.cpp b/soh/soh/Network/CrowdControl/CrowdControl.cpp index 84f15bc2f99..ab9630879b2 100644 --- a/soh/soh/Network/CrowdControl/CrowdControl.cpp +++ b/soh/soh/Network/CrowdControl/CrowdControl.cpp @@ -391,9 +391,8 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { // Give Items and Consumables case kEffectAddHeartContainer: - RegisterHeartSpawner(); effect->giEffect = new GameInteractionEffect::ModifyHeartContainers(); - //dynamic_cast(effect->giEffect)->parameters[0] = 1; + dynamic_cast(effect->giEffect)->parameters[0] = 1; break; case kEffectFillMagic: effect->giEffect = new GameInteractionEffect::FillMagic();