Fairysanity: allow using bottle (#6021)
Based on fishsanity, which is refactored with hooks Also open up logic catching fairies at oasis if player has bottle
This commit is contained in:
@@ -98,17 +98,22 @@ void RegisterShuffleFairies() {
|
|||||||
// Grant item when picking up fairy.
|
// Grant item when picking up fairy.
|
||||||
COND_VB_SHOULD(VB_FAIRY_HEAL, shouldRegister, {
|
COND_VB_SHOULD(VB_FAIRY_HEAL, shouldRegister, {
|
||||||
EnElf* enElf = va_arg(args, EnElf*);
|
EnElf* enElf = va_arg(args, EnElf*);
|
||||||
|
|
||||||
const auto fairyIdentity = ObjectExtension::GetInstance().Get<FairyIdentity>(&enElf->actor);
|
const auto fairyIdentity = ObjectExtension::GetInstance().Get<FairyIdentity>(&enElf->actor);
|
||||||
if (fairyIdentity == nullptr) {
|
if (fairyIdentity != nullptr && fairyIdentity->randomizerInf != RAND_INF_MAX) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fairyIdentity != nullptr && fairyIdentity->randomizerInf && fairyIdentity->randomizerInf != RAND_INF_MAX) {
|
|
||||||
Flags_SetRandomizerInf(fairyIdentity->randomizerInf);
|
Flags_SetRandomizerInf(fairyIdentity->randomizerInf);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
COND_VB_SHOULD(VB_BOTTLE_ACTOR, shouldRegister, {
|
||||||
|
Actor* actor = va_arg(args, Actor*);
|
||||||
|
const auto fairyIdentity = ObjectExtension::GetInstance().Get<FairyIdentity>(actor);
|
||||||
|
if (fairyIdentity != nullptr && fairyIdentity->randomizerInf != RAND_INF_MAX) {
|
||||||
|
Flags_SetRandomizerInf(fairyIdentity->randomizerInf);
|
||||||
|
actor->parent = &GET_PLAYER(gPlayState)->actor;
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Spawn fairies in fairy fountains
|
// Spawn fairies in fairy fountains
|
||||||
COND_VB_SHOULD(VB_SPAWN_FOUNTAIN_FAIRIES, shouldRegisterFountain, {
|
COND_VB_SHOULD(VB_SPAWN_FOUNTAIN_FAIRIES, shouldRegisterFountain, {
|
||||||
Actor* actor = va_arg(args, Actor*);
|
Actor* actor = va_arg(args, Actor*);
|
||||||
|
|||||||
@@ -51,11 +51,12 @@ ActorFunc drawFishing = NULL;
|
|||||||
ActorFunc drawEnFish = NULL;
|
ActorFunc drawEnFish = NULL;
|
||||||
Color_RGB8 fsPulseColor = { 30, 240, 200 };
|
Color_RGB8 fsPulseColor = { 30, 240, 200 };
|
||||||
|
|
||||||
|
static s16 fishGroupCounter = 0;
|
||||||
|
static bool enableAdvance = false;
|
||||||
|
|
||||||
namespace Rando {
|
namespace Rando {
|
||||||
const FishIdentity Fishsanity::defaultIdentity = { RAND_INF_MAX, RC_UNKNOWN_CHECK };
|
const FishIdentity Fishsanity::defaultIdentity = { RAND_INF_MAX, RC_UNKNOWN_CHECK };
|
||||||
bool Fishsanity::fishsanityHelpersInit = false;
|
bool Fishsanity::fishsanityHelpersInit = false;
|
||||||
s16 Fishsanity::fishGroupCounter = 0;
|
|
||||||
bool Fishsanity::enableAdvance = false;
|
|
||||||
std::unordered_map<RandomizerCheck, LinkAge> Fishsanity::pondFishAgeMap;
|
std::unordered_map<RandomizerCheck, LinkAge> Fishsanity::pondFishAgeMap;
|
||||||
std::vector<RandomizerCheck> Fishsanity::childPondFish;
|
std::vector<RandomizerCheck> Fishsanity::childPondFish;
|
||||||
std::vector<RandomizerCheck> Fishsanity::adultPondFish;
|
std::vector<RandomizerCheck> Fishsanity::adultPondFish;
|
||||||
@@ -447,38 +448,6 @@ void Fishsanity::OnActorUpdateHandler(void* refActor) {
|
|||||||
fishGroupCounter = 0;
|
fishGroupCounter = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fishsanity::OnSceneInitHandler(int16_t sceneNum) {
|
|
||||||
if (sceneNum == SCENE_ZORAS_DOMAIN) {
|
|
||||||
fishGroupCounter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fishsanity::OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs) {
|
|
||||||
va_list args;
|
|
||||||
va_copy(args, originalArgs);
|
|
||||||
|
|
||||||
Actor* actor = va_arg(args, Actor*);
|
|
||||||
auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
|
|
||||||
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
if (id == VB_BOTTLE_ACTOR && actor->id == ACTOR_EN_FISH && fs->GetOverworldFishShuffled()) {
|
|
||||||
FishIdentity fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
|
|
||||||
if (fish.randomizerCheck != RC_UNKNOWN_CHECK && !Flags_GetRandomizerInf(fish.randomizerInf)) {
|
|
||||||
Flags_SetRandomizerInf(fish.randomizerInf);
|
|
||||||
actor->parent = &GET_PLAYER(gPlayState)->actor;
|
|
||||||
*should = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fishsanity::OnItemReceiveHandler(GetItemEntry itemEntry) {
|
|
||||||
if (enableAdvance) {
|
|
||||||
enableAdvance = false;
|
|
||||||
OTRGlobals::Instance->gRandoContext->GetFishsanity()->AdvancePond();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace Rando
|
} // namespace Rando
|
||||||
|
|
||||||
// C interface
|
// C interface
|
||||||
@@ -575,6 +544,37 @@ void Fishsanity_CloseGreyscaleColor(PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegisterShuffleFish() {
|
||||||
|
bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_FISHSANITY) != RO_FISHSANITY_OFF;
|
||||||
|
COND_HOOK(OnSceneInit, shouldRegister, [](int16_t sceneNum) {
|
||||||
|
if (sceneNum == SCENE_ZORAS_DOMAIN) {
|
||||||
|
fishGroupCounter = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
COND_HOOK(OnActorInit, shouldRegister, Rando::Fishsanity::OnActorInitHandler);
|
||||||
|
COND_HOOK(OnActorUpdate, shouldRegister, Rando::Fishsanity::OnActorUpdateHandler);
|
||||||
|
COND_HOOK(OnItemReceive, shouldRegister, [](GetItemEntry itemEntry) {
|
||||||
|
if (enableAdvance) {
|
||||||
|
enableAdvance = false;
|
||||||
|
OTRGlobals::Instance->gRandoContext->GetFishsanity()->AdvancePond();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
COND_VB_SHOULD(VB_BOTTLE_ACTOR, shouldRegister, {
|
||||||
|
Actor* actor = va_arg(args, Actor*);
|
||||||
|
auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
|
||||||
|
if (actor->id == ACTOR_EN_FISH && fs->GetOverworldFishShuffled()) {
|
||||||
|
FishIdentity fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
|
||||||
|
if (fish.randomizerCheck != RC_UNKNOWN_CHECK && !Flags_GetRandomizerInf(fish.randomizerInf)) {
|
||||||
|
Flags_SetRandomizerInf(fish.randomizerInf);
|
||||||
|
actor->parent = &GET_PLAYER(gPlayState)->actor;
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Rando::StaticData::RegisterFishLocations() {
|
void Rando::StaticData::RegisterFishLocations() {
|
||||||
static bool registered = false;
|
static bool registered = false;
|
||||||
if (registered)
|
if (registered)
|
||||||
@@ -634,4 +634,5 @@ void Rando::StaticData::RegisterFishLocations() {
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc registerShuffleFish(RegisterShuffleFish, { "IS_RANDO" });
|
||||||
static RegisterShipInitFunc initFunc(Rando::StaticData::RegisterFishLocations);
|
static RegisterShipInitFunc initFunc(Rando::StaticData::RegisterFishLocations);
|
||||||
|
|||||||
@@ -137,28 +137,11 @@ class Fishsanity {
|
|||||||
*/
|
*/
|
||||||
static void OnActorInitHandler(void* refActor);
|
static void OnActorInitHandler(void* refActor);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PlayerUpdate hook handler for fishsanity
|
|
||||||
*/
|
|
||||||
static void OnPlayerUpdateHandler();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ActorUpdate hook handler for fishsanity
|
* @brief ActorUpdate hook handler for fishsanity
|
||||||
*/
|
*/
|
||||||
static void OnActorUpdateHandler(void* refActor);
|
static void OnActorUpdateHandler(void* refActor);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief SceneInit hook handler for fishsanity
|
|
||||||
*/
|
|
||||||
static void OnSceneInitHandler(int16_t sceneNum);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief VB hook handler for fishsanity
|
|
||||||
*/
|
|
||||||
static void OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs);
|
|
||||||
|
|
||||||
static void OnItemReceiveHandler(GetItemEntry itemEntry);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Initialize helper statics if they have not been initialized yet
|
* @brief Initialize helper statics if they have not been initialized yet
|
||||||
@@ -184,9 +167,6 @@ class Fishsanity {
|
|||||||
*/
|
*/
|
||||||
static bool fishsanityHelpersInit;
|
static bool fishsanityHelpersInit;
|
||||||
|
|
||||||
static s16 fishGroupCounter;
|
|
||||||
static bool enableAdvance;
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////
|
||||||
//// Helper data structures derived from static data ////
|
//// Helper data structures derived from static data ////
|
||||||
/////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include "soh/Enhancements/item-tables/ItemTableManager.h"
|
#include "soh/Enhancements/item-tables/ItemTableManager.h"
|
||||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||||
#include "soh/Enhancements/randomizer/dungeon.h"
|
#include "soh/Enhancements/randomizer/dungeon.h"
|
||||||
#include "soh/Enhancements/randomizer/fishsanity.h"
|
|
||||||
#include "soh/Enhancements/randomizer/static_data.h"
|
#include "soh/Enhancements/randomizer/static_data.h"
|
||||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
@@ -2438,12 +2437,6 @@ void RandomizerRegisterHooks() {
|
|||||||
static uint32_t onKaleidoUpdateHook = 0;
|
static uint32_t onKaleidoUpdateHook = 0;
|
||||||
static uint32_t onCuccoOrChickenHatchHook = 0;
|
static uint32_t onCuccoOrChickenHatchHook = 0;
|
||||||
|
|
||||||
static uint32_t fishsanityOnActorInitHook = 0;
|
|
||||||
static uint32_t fishsanityOnActorUpdateHook = 0;
|
|
||||||
static uint32_t fishsanityOnSceneInitHook = 0;
|
|
||||||
static uint32_t fishsanityOnVanillaBehaviorHook = 0;
|
|
||||||
static uint32_t fishsanityOnItemReceiveHook = 0;
|
|
||||||
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) {
|
||||||
ShipInit::Init("IS_RANDO");
|
ShipInit::Init("IS_RANDO");
|
||||||
|
|
||||||
@@ -2470,13 +2463,6 @@ void RandomizerRegisterHooks() {
|
|||||||
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnKaleidoscopeUpdate>(onKaleidoUpdateHook);
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnKaleidoscopeUpdate>(onKaleidoUpdateHook);
|
||||||
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnCuccoOrChickenHatch>(onCuccoOrChickenHatchHook);
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnCuccoOrChickenHatch>(onCuccoOrChickenHatchHook);
|
||||||
|
|
||||||
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(fishsanityOnActorInitHook);
|
|
||||||
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(fishsanityOnActorUpdateHook);
|
|
||||||
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(fishsanityOnSceneInitHook);
|
|
||||||
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(
|
|
||||||
fishsanityOnVanillaBehaviorHook);
|
|
||||||
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnItemReceive>(fishsanityOnItemReceiveHook);
|
|
||||||
|
|
||||||
onFlagSetHook = 0;
|
onFlagSetHook = 0;
|
||||||
onSceneFlagSetHook = 0;
|
onSceneFlagSetHook = 0;
|
||||||
onPlayerUpdateForRCQueueHook = 0;
|
onPlayerUpdateForRCQueueHook = 0;
|
||||||
@@ -2496,12 +2482,6 @@ void RandomizerRegisterHooks() {
|
|||||||
onKaleidoUpdateHook = 0;
|
onKaleidoUpdateHook = 0;
|
||||||
onCuccoOrChickenHatchHook = 0;
|
onCuccoOrChickenHatchHook = 0;
|
||||||
|
|
||||||
fishsanityOnActorInitHook = 0;
|
|
||||||
fishsanityOnActorUpdateHook = 0;
|
|
||||||
fishsanityOnSceneInitHook = 0;
|
|
||||||
fishsanityOnVanillaBehaviorHook = 0;
|
|
||||||
fishsanityOnItemReceiveHook = 0;
|
|
||||||
|
|
||||||
if (!IS_RANDO)
|
if (!IS_RANDO)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -2553,18 +2533,6 @@ void RandomizerRegisterHooks() {
|
|||||||
|
|
||||||
if (RAND_GET_OPTION(RSK_FISHSANITY) != RO_FISHSANITY_OFF) {
|
if (RAND_GET_OPTION(RSK_FISHSANITY) != RO_FISHSANITY_OFF) {
|
||||||
OTRGlobals::Instance->gRandoContext->GetFishsanity()->InitializeFromSave();
|
OTRGlobals::Instance->gRandoContext->GetFishsanity()->InitializeFromSave();
|
||||||
|
|
||||||
fishsanityOnActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(
|
|
||||||
Rando::Fishsanity::OnActorInitHandler);
|
|
||||||
fishsanityOnActorUpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>(
|
|
||||||
Rando::Fishsanity::OnActorUpdateHandler);
|
|
||||||
fishsanityOnSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(
|
|
||||||
Rando::Fishsanity::OnSceneInitHandler);
|
|
||||||
fishsanityOnVanillaBehaviorHook =
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(
|
|
||||||
Rando::Fishsanity::OnVanillaBehaviorHandler);
|
|
||||||
fishsanityOnItemReceiveHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(
|
|
||||||
Rando::Fishsanity::OnItemReceiveHandler);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ void RegionTable_Init_DesertColossus() {
|
|||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
//You can kinda get the fairies without entering the water, but it relies on them cooperating and leevers are jerks. should be a trick
|
//You can kinda get the fairies without entering the water, but it relies on them cooperating and leevers are jerks. should be a trick
|
||||||
Entrance(RR_DESERT_COLOSSUS_OASIS, []{return logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS));}),
|
Entrance(RR_DESERT_COLOSSUS_OASIS, []{return logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_EMPTY_BOTTLE));}),
|
||||||
Entrance(RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, []{return logic->HasExplosives();}),
|
Entrance(RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, []{return logic->HasExplosives();}),
|
||||||
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}),
|
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}),
|
||||||
Entrance(RR_WASTELAND_NEAR_COLOSSUS, []{return true;}),
|
Entrance(RR_WASTELAND_NEAR_COLOSSUS, []{return true;}),
|
||||||
|
|||||||
Reference in New Issue
Block a user