Refactor Fishsanity (#4268)

* Move Fishsanity hooks out of mods.cpp

* Assign fish check flags.

* Clean up location_list for fish

* Prevent fishing from giving double items.

* Remove no-longer-used mPendingFish

* Override draw function for fishing

This allows the draw functions in the source
overlay to match the decomp.

* Override draw function for EnFish

* Overwrite grotto fish params based on respawn data

This allows the randomizer to identify them
automatically without any special logic.

The catch (pun not intended) is that grotto fish don't respawn,
and they were previously identified for such by a params value of 1,
so the logic to take care of that needed to be duplicated.
Thankfully it wasn't very much.

* Add a VB for catching actors in bottles.

* Clean up remaining code after conversion to VB

This breaks fast FastDrops for bottle pickups, though
readding it shouldn't be too hard with the VB hook.

* Remove fishsanityParams from Fishing

It was previously used to track exactly which fish would be
released after a catch, but since both candidate fish
would've been caught, they both wouldn't give checks
anyways.

* Update soh/soh/Enhancements/randomizer/hook_handlers.cpp

Co-authored-by: Pepe20129 <72659707+Pepe20129@users.noreply.github.com>

* Re-add FastDrops for bottle pickups.

While this does diverge from the vanilla decomp, I'm uncertain of
the order that hooks are run, so I put it back into z_player.c
just to be safe. A future commit can do a more proper implementation
using VB hooks.

* Move initialisation of fishsanity hooks into hook_handlers

* Change location constructor to take RandomizerInf instead of uint8_t

This shouldn't have an effect as-is, but other changes can add
additional randomizer flags that can end up pushing fishsanity check
flags out of the range of a uint8_t, causing the cast to overflow
and not be stored correctly. With this change, it could still overflow
when writing to the flag field of Location, but said field is unused
and the parameter is really only for setting the flag for the
SpoilerCollectionCheck.

* Render uncaught overworld fish as randomized item

* Fix windows build by zeroing unused field

* Fix scene parameter type

This resolves a build error on Mac and Windows, but Linux
instead buries it in the sea of warnings, meaning I can't
see it until it fails CI.

---------

Co-authored-by: Pepe20129 <72659707+Pepe20129@users.noreply.github.com>
This commit is contained in:
Angelo Bulfone 2024-10-02 09:37:15 -07:00 committed by GitHub
parent e36dcefe54
commit 89ca2149b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 306 additions and 359 deletions

View File

@ -421,6 +421,11 @@ typedef enum {
// Vanilla condition: true // Vanilla condition: true
VB_PHANTOM_GANON_DEATH_SCENE, VB_PHANTOM_GANON_DEATH_SCENE,
VB_NABOORU_KNUCKLE_DEATH_SCENE, VB_NABOORU_KNUCKLE_DEATH_SCENE,
/*** Fishsanity ***/
// Vanilla condition: Actor is ACTOR_EN_ELF, ACTOR_EN_FISH, ACTOR_EN_ICE_HONO, or ACTOR_EN_INSECT
// Opt: *Actor
VB_BOTTLE_ACTOR,
} GIVanillaBehavior; } GIVanillaBehavior;
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -6,7 +6,6 @@
#include "soh/Enhancements/boss-rush/BossRushTypes.h" #include "soh/Enhancements/boss-rush/BossRushTypes.h"
#include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/randomizer/3drando/random.hpp" #include "soh/Enhancements/randomizer/3drando/random.hpp"
#include "soh/Enhancements/randomizer/fishsanity.h"
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h" #include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
#include <soh/Enhancements/item-tables/ItemTableManager.h> #include <soh/Enhancements/item-tables/ItemTableManager.h>
#include "soh/Enhancements/nametag.h" #include "soh/Enhancements/nametag.h"
@ -1545,156 +1544,6 @@ void RegisterNoWallet() {
}); });
} }
void RegisterFishsanity() {
static s16 fishGroupCounter = 0;
// Initialization on load
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) {
if (!IS_RANDO) {
return;
}
OTRGlobals::Instance->gRandoContext->GetFishsanity()->InitializeFromSave();
});
// Initialize actors for fishsanity
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
if (!IS_RANDO) {
return;
}
Actor* actor = static_cast<Actor*>(refActor);
auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
FishIdentity fish;
if (actor->id == ACTOR_EN_FISH && fs->GetOverworldFishShuffled()) {
// Set fish ID for ZD fish
if (gPlayState->sceneNum == SCENE_ZORAS_DOMAIN && actor->params == -1) {
actor->params ^= fishGroupCounter++;
}
fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
// Create effect for uncaught fish
if (Rando::Fishsanity::IsFish(&fish) && !Flags_GetRandomizerInf(fish.randomizerInf)) {
actor->shape.shadowDraw = Fishsanity_DrawEffShadow;
}
return;
}
if (actor->id == ACTOR_FISHING && gPlayState->sceneNum == SCENE_FISHING_POND && actor->params >= 100 &&
actor->params <= 117 && fs->GetPondFishShuffled()) {
// Initialize pond fish for fishsanity
// Initialize fishsanity metadata on this actor
Fishing* fishActor = static_cast<Fishing*>(refActor);
fishActor->fishsanityParams = actor->params;
fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
// With every pond fish shuffled, caught fish will not spawn unless all fish have been caught.
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_POND_COUNT) > 16 &&
!fs->GetPondCleared()) {
// Create effect for uncaught fish
if (!Flags_GetRandomizerInf(fish.randomizerInf)) {
actor->shape.shadowDraw = Fishsanity_DrawEffShadow;
}
}
}
});
// Update fishsanity when a fish is caught
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>([](int16_t flagType, int16_t flag) {
if (!IS_RANDO || flagType != FLAG_RANDOMIZER_INF) {
return;
}
RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)flag);
FishsanityCheckType fsType = Rando::Fishsanity::GetCheckType(rc);
if (fsType == FSC_NONE) {
return;
}
// When a pond fish is caught, advance the pond.
if (fsType == FSC_POND) {
OTRGlobals::Instance->gRandoContext->GetFishsanity()->AdvancePond();
}
});
// Award fishing pond checks
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
if (!IS_RANDO || GameInteractor::IsGameplayPaused() || !gPlayState) {
return;
}
Player* player = GET_PLAYER(gPlayState);
if (Player_InBlockingCsMode(gPlayState, player)) {
return;
}
auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
if (!fs->GetPondFishShuffled()) {
return;
}
FishIdentity pending = fs->GetPendingFish();
if (!Rando::Fishsanity::IsFish(&pending)) { // No fish currently pending
return;
}
// Award fish
GetItemEntry gi = OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(pending.randomizerCheck, GI_NONE);
Flags_SetRandomizerInf(pending.randomizerInf);
GiveItemEntryWithoutActor(gPlayState, gi);
fs->SetPendingFish(NULL);
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
if (!IS_RANDO || (gPlayState->sceneNum != SCENE_GROTTOS && gPlayState->sceneNum != SCENE_ZORAS_DOMAIN && gPlayState->sceneNum != SCENE_FISHING_POND)) {
return;
}
Actor* actor = static_cast<Actor*>(refActor);
auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
// Detect fish catch
if (actor->id == ACTOR_FISHING && fs->GetPondFishShuffled()) {
Fishing* fish = static_cast<Fishing*>(refActor);
// State 6 -> Fish caught and hoisted
FishIdentity pending = fs->GetPendingFish();
if (fish->fishState == 6 && !Rando::Fishsanity::IsFish(&pending)) {
pending = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, fish->fishsanityParams);
if (!Flags_GetRandomizerInf(pending.randomizerInf)) {
fs->SetPendingFish(&pending);
// Remove uncaught effect
if (actor->shape.shadowDraw != NULL) {
actor->shape.shadowDraw = NULL;
}
}
}
}
if (actor->id == ACTOR_EN_FISH && fs->GetOverworldFishShuffled()) {
FishIdentity fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
if (Rando::Fishsanity::IsFish(&fish) && Flags_GetRandomizerInf(fish.randomizerInf)) {
// Remove uncaught effect
if (actor->shape.shadowDraw != NULL) {
actor->shape.shadowDraw = NULL;
}
}
}
// Reset fish group counter when the group gets culled
if (actor->id == ACTOR_OBJ_MURE && gPlayState->sceneNum == SCENE_ZORAS_DOMAIN && fishGroupCounter > 0 &&
!(actor->flags & ACTOR_FLAG_UPDATE_WHILE_CULLED) && fs->GetOverworldFishShuffled()) {
fishGroupCounter = 0;
}
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
if (!IS_RANDO || sceneNum != SCENE_ZORAS_DOMAIN)
return;
fishGroupCounter = 0;
});
}
void RegisterInfiniteUpgrades() { void RegisterInfiniteUpgrades() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (!IS_RANDO) { if (!IS_RANDO) {
@ -1819,7 +1668,6 @@ void InitMods() {
RegisterToTMedallions(); RegisterToTMedallions();
RegisterNoSwim(); RegisterNoSwim();
RegisterNoWallet(); RegisterNoWallet();
RegisterFishsanity();
RegisterInfiniteUpgrades(); RegisterInfiniteUpgrades();
RegisterRandomizerCompasses(); RegisterRandomizerCompasses();
NameTag_RegisterHooks(); NameTag_RegisterHooks();

View File

@ -1,13 +1,24 @@
#include "3drando/pool_functions.hpp" #include "3drando/pool_functions.hpp"
#include "../../OTRGlobals.h" #include "../../OTRGlobals.h"
#include "fishsanity.h" #include "fishsanity.h"
#include "draw.h"
#include "variables.h" #include "variables.h"
#include "functions.h" #include "functions.h"
#include "macros.h" #include "macros.h"
#include <consolevariablebridge.h> #include <consolevariablebridge.h>
extern "C" {
#include "src/overlays/actors/ovl_Fishing/z_fishing.h"
#include "src/overlays/actors/ovl_En_Fish/z_en_fish.h"
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
}
#define FSi OTRGlobals::Instance->gRandoContext->GetFishsanity() #define FSi OTRGlobals::Instance->gRandoContext->GetFishsanity()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex()
/** /**
* @brief Parallel list of pond fish checks for both ages * @brief Parallel list of pond fish checks for both ages
*/ */
@ -40,9 +51,14 @@ std::unordered_map<int8_t, RandomizerCheck> Rando::StaticData::randomizerGrottoF
{ 0x29, RC_ZR_OPEN_GROTTO_FISH } { 0x29, RC_ZR_OPEN_GROTTO_FISH }
}; };
ActorFunc drawFishing = NULL;
ActorFunc drawEnFish = NULL;
Color_RGBA16 fsPulseColor = { 30, 240, 200 };
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;
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;
@ -75,7 +91,7 @@ namespace Rando {
} }
// Are overworld fish enabled, and is this an overworld fish location? // Are overworld fish enabled, and is this an overworld fish location?
if (mode != RO_FISHSANITY_POND && (loc->GetScene() == SCENE_GROTTOS || loc->GetScene() == SCENE_ZORAS_DOMAIN) if (mode != RO_FISHSANITY_POND && (loc->GetScene() == SCENE_GROTTOS || loc->GetScene() == SCENE_ZORAS_DOMAIN)
&& loc->GetActorID() == ACTOR_EN_FISH && (loc->GetActorParams() == 1 || loc->GetActorParams() < 0)) { && loc->GetActorID() == ACTOR_EN_FISH && (loc->GetActorParams() >> 8)) {
return true; return true;
} }
// Must not be an included fish location! // Must not be an included fish location!
@ -321,12 +337,136 @@ namespace Rando {
return GetCheckType(fish->randomizerCheck) != FSC_NONE; return GetCheckType(fish->randomizerCheck) != FSC_NONE;
} }
void Fishsanity::SetPendingFish(FishIdentity* fish) { void Fishsanity::OnActorInitHandler(void* refActor) {
mPendingFish = fish == NULL ? defaultIdentity : *fish; Actor* actor = static_cast<Actor*>(refActor);
auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
FishIdentity fish;
if (actor->id == ACTOR_EN_FISH && fs->GetOverworldFishShuffled()) {
// Set fish ID for ZD fish
if (gPlayState->sceneNum == SCENE_ZORAS_DOMAIN && actor->params == -1) {
actor->params ^= fishGroupCounter++;
} else if (gPlayState->sceneNum == SCENE_GROTTOS && actor->params == 1) {
actor->params = 0x100 | gSaveContext.respawn[RESPAWN_MODE_RETURN].data;
}
fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
// Render fish as randomized item
if (Rando::Fishsanity::IsFish(&fish) && !Flags_GetRandomizerInf(fish.randomizerInf)) {
if (!drawEnFish) {
drawEnFish = actor->draw;
}
actor->draw = Fishsanity_DrawEnFish;
}
return;
}
if (actor->id == ACTOR_FISHING && gPlayState->sceneNum == SCENE_FISHING_POND && actor->params >= 100 &&
actor->params <= 117 && fs->GetPondFishShuffled()) {
// Initialize pond fish for fishsanity
// Initialize fishsanity metadata on this actor
Fishing* fishActor = static_cast<Fishing*>(refActor);
//fishActor->fishsanityParams = actor->params;
fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
// With every pond fish shuffled, caught fish will not spawn unless all fish have been caught.
if (RAND_GET_OPTION(RSK_FISHSANITY_POND_COUNT) > 16 &&
!fs->GetPondCleared()) {
// Create effect for uncaught fish
if (!Flags_GetRandomizerInf(fish.randomizerInf)) {
actor->shape.shadowDraw = Fishsanity_DrawEffShadow;
if (!drawFishing) {
drawFishing = actor->draw;
}
actor->draw = Fishsanity_DrawFishing;
}
}
}
} }
FishIdentity Fishsanity::GetPendingFish() { void Fishsanity::OnFlagSetHandler(int16_t flagType, int16_t flag) {
return mPendingFish; if (flagType != FLAG_RANDOMIZER_INF) {
return;
}
RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)flag);
FishsanityCheckType fsType = Rando::Fishsanity::GetCheckType(rc);
if (fsType == FSC_NONE) {
return;
}
// When a pond fish is caught, advance the pond.
if (fsType == FSC_POND) {
OTRGlobals::Instance->gRandoContext->GetFishsanity()->AdvancePond();
}
}
void Fishsanity::OnActorUpdateHandler(void* refActor) {
if (gPlayState->sceneNum != SCENE_GROTTOS && gPlayState->sceneNum != SCENE_ZORAS_DOMAIN && gPlayState->sceneNum != SCENE_FISHING_POND) {
return;
}
Actor* actor = static_cast<Actor*>(refActor);
auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
// Detect fish catch
if (actor->id == ACTOR_FISHING && fs->GetPondFishShuffled()) {
Fishing* fish = static_cast<Fishing*>(refActor);
// State 6 -> Fish caught and hoisted
if (fish->fishState == 6) {
FishIdentity identity = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
if (identity.randomizerCheck != RC_UNKNOWN_CHECK) {
Flags_SetRandomizerInf(identity.randomizerInf);
// Remove uncaught effect
if (actor->shape.shadowDraw != NULL) {
actor->shape.shadowDraw = NULL;
actor->draw = drawFishing;
}
}
}
}
if (actor->id == ACTOR_EN_FISH && fs->GetOverworldFishShuffled()) {
FishIdentity fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
EnFish* fishActor = static_cast<EnFish*>(refActor);
if (Rando::Fishsanity::IsFish(&fish) && Flags_GetRandomizerInf(fish.randomizerInf)) {
// Reset draw method
if (actor->draw == Fishsanity_DrawEnFish) {
actor->draw = drawEnFish;
}
}
if (((actor->params >> 8) > 0) && fishActor->respawnTimer > 0) {
Actor_Kill(actor);
}
}
// Reset fish group counter when the group gets culled
if (actor->id == ACTOR_OBJ_MURE && gPlayState->sceneNum == SCENE_ZORAS_DOMAIN && fishGroupCounter > 0 &&
!(actor->flags & ACTOR_FLAG_UPDATE_WHILE_CULLED) && fs->GetOverworldFishShuffled()) {
fishGroupCounter = 0;
}
}
void Fishsanity::OnSceneInitHandler(int16_t sceneNum) {
if (sceneNum == SCENE_ZORAS_DOMAIN) {
fishGroupCounter = 0;
}
}
void Fishsanity::OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* refActor) {
Actor* actor = static_cast<Actor*>(refActor);
auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
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;
}
}
} }
} // namespace Rando } // namespace Rando
@ -344,10 +484,6 @@ extern "C" {
return FSi->IsAdultPond(); return FSi->IsAdultPond();
} }
void Randomizer_SetPendingFish(FishIdentity* fish) {
return FSi->SetPendingFish(fish);
}
void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play) { void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play) {
Vec3f pos, ripplePos; Vec3f pos, ripplePos;
static Vec3f velocity = { 0.0f, 0.0f, 0.0f }; static Vec3f velocity = { 0.0f, 0.0f, 0.0f };
@ -394,6 +530,28 @@ extern "C" {
} }
} }
void Fishsanity_DrawEnFish(struct Actor* actor, struct PlayState* play) {
FishIdentity fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(play->sceneNum, actor->params);
GetItemEntry randoItem = Rando::Context::GetInstance()->GetFinalGIEntry(fish.randomizerCheck, true, GI_FISH);
if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) {
randoItem = GET_ITEM_MYSTERY;
}
Matrix_Push();
Matrix_Scale(30.0, 30.0, 30.0, MTXMODE_APPLY);
EnItem00_CustomItemsParticles(actor, play, randoItem);
GetItemEntry_Draw(play, randoItem);
Matrix_Pop();
}
void Fishsanity_DrawFishing(struct Actor* actor, struct PlayState* play) {
Fishsanity_OpenGreyscaleColor(play, &fsPulseColor, (actor->params - 100) * 20);
drawFishing(actor, play);
Fishsanity_CloseGreyscaleColor(play);
}
void Fishsanity_OpenGreyscaleColor(PlayState* play, Color_RGBA16* color, int16_t frameOffset) { void Fishsanity_OpenGreyscaleColor(PlayState* play, Color_RGBA16* color, int16_t frameOffset) {
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
gDPSetGrayscaleColor( gDPSetGrayscaleColor(

View File

@ -4,6 +4,7 @@
#include <z64.h> #include <z64.h>
#include "randomizerTypes.h" #include "randomizerTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
typedef struct FishsanityPondOptions { typedef struct FishsanityPondOptions {
u8 mode; u8 mode;
@ -128,15 +129,34 @@ class Fishsanity {
FishIdentity AdvancePond(); FishIdentity AdvancePond();
/** /**
* @brief Set the currently held fish * @brief ActorInit hook handler for fishsanity
* @param fish Pointer to FishIdentity to copy
*/ */
void SetPendingFish(FishIdentity* fish); static void OnActorInitHandler(void* refActor);
/** /**
* @brief Get the currently held fish * @brief FlagSet hook handler for fishsanity
*/ */
FishIdentity GetPendingFish(); static void OnFlagSetHandler(int16_t flagType, int16_t flag);
/**
* @brief PlayerUpdate hook handler for fishsanity
*/
static void OnPlayerUpdateHandler();
/**
* @brief ActorUpdate hook handler for fishsanity
*/
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, void* refActor);
private: private:
/** /**
@ -152,22 +172,19 @@ class Fishsanity {
* @return The FishIdentity for the described fish * @return The FishIdentity for the described fish
*/ */
static FishIdentity GetPondFish(s16 params, bool adultPond); static FishIdentity GetPondFish(s16 params, bool adultPond);
/** /**
* @brief Current pond fish when all pond fish are not randomized * @brief Current pond fish when all pond fish are not randomized
*/ */
std::pair<FishIdentity, FishIdentity> mCurrPondFish; std::pair<FishIdentity, FishIdentity> mCurrPondFish;
/**
* @brief Identity of the last-caught fish in the fishing pond minigame awaiting reward
*/
FishIdentity mPendingFish;
/** /**
* @brief True if fishsanity helpers have been initialized * @brief True if fishsanity helpers have been initialized
*/ */
static bool fishsanityHelpersInit; static bool fishsanityHelpersInit;
static s16 fishGroupCounter;
///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////
//// Helper data structures derived from static data //// //// Helper data structures derived from static data ////
///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////
@ -197,10 +214,12 @@ bool Randomizer_GetPondFishShuffled();
bool Randomizer_GetOverworldFishShuffled(); bool Randomizer_GetOverworldFishShuffled();
/// Returns true if the adult fishing pond should be used for fishsanity. /// Returns true if the adult fishing pond should be used for fishsanity.
bool Randomizer_IsAdultPond(); bool Randomizer_IsAdultPond();
/// Sets the pending fish
void Randomizer_SetPendingFish(FishIdentity* fish);
/// Custom shadow draw function to add effect to uncollected fish /// Custom shadow draw function to add effect to uncollected fish
void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play); void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play);
/// Overriden actor draw function for bottleable fish
void Fishsanity_DrawEnFish(struct Actor* actor, struct PlayState* play);
/// Overriden actor draw function for the fishing pond
void Fishsanity_DrawFishing(struct Actor* actor, struct PlayState* play);
void Fishsanity_OpenGreyscaleColor(PlayState* play, Color_RGBA16* color, int16_t frameOffset); void Fishsanity_OpenGreyscaleColor(PlayState* play, Color_RGBA16* color, int16_t frameOffset);
void Fishsanity_CloseGreyscaleColor(PlayState* play); void Fishsanity_CloseGreyscaleColor(PlayState* play);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -4,6 +4,7 @@
#include "soh/Enhancements/custom-message/CustomMessageTypes.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.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/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"
@ -1525,6 +1526,12 @@ void RandomizerRegisterHooks() {
static uint32_t onSceneInitHook = 0; static uint32_t onSceneInitHook = 0;
static uint32_t onActorInitHook = 0; static uint32_t onActorInitHook = 0;
static uint32_t fishsanityOnActorInitHook = 0;
static uint32_t fishsanityOnFlagSetHook = 0;
static uint32_t fishsanityOnActorUpdateHook = 0;
static uint32_t fishsanityOnSceneInitHook = 0;
static uint32_t fishsanityOnVanillaBehaviorHook = 0;
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) {
randomizerQueuedChecks = std::queue<RandomizerCheck>(); randomizerQueuedChecks = std::queue<RandomizerCheck>();
randomizerQueuedCheck = RC_UNKNOWN_CHECK; randomizerQueuedCheck = RC_UNKNOWN_CHECK;
@ -1539,6 +1546,12 @@ void RandomizerRegisterHooks() {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(onSceneInitHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(onSceneInitHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(onActorInitHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(onActorInitHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(fishsanityOnActorInitHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnFlagSet>(fishsanityOnFlagSetHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(fishsanityOnActorUpdateHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(fishsanityOnSceneInitHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(fishsanityOnVanillaBehaviorHook);
onFlagSetHook = 0; onFlagSetHook = 0;
onSceneFlagSetHook = 0; onSceneFlagSetHook = 0;
onPlayerUpdateForRCQueueHook = 0; onPlayerUpdateForRCQueueHook = 0;
@ -1548,6 +1561,12 @@ void RandomizerRegisterHooks() {
onSceneInitHook = 0; onSceneInitHook = 0;
onActorInitHook = 0; onActorInitHook = 0;
fishsanityOnActorInitHook = 0;
fishsanityOnFlagSetHook = 0;
fishsanityOnActorUpdateHook = 0;
fishsanityOnSceneInitHook = 0;
fishsanityOnVanillaBehaviorHook = 0;
if (!IS_RANDO) return; if (!IS_RANDO) return;
onFlagSetHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(RandomizerOnFlagSetHandler); onFlagSetHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(RandomizerOnFlagSetHandler);
@ -1558,5 +1577,15 @@ void RandomizerRegisterHooks() {
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(RandomizerOnVanillaBehaviorHandler); onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(RandomizerOnVanillaBehaviorHandler);
onSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(RandomizerOnSceneInitHandler); onSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(RandomizerOnSceneInitHandler);
onActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(RandomizerOnActorInitHandler); onActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(RandomizerOnActorInitHandler);
if (RAND_GET_OPTION(RSK_FISHSANITY) != RO_FISHSANITY_OFF) {
OTRGlobals::Instance->gRandoContext->GetFishsanity()->InitializeFromSave();
fishsanityOnActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(Rando::Fishsanity::OnActorInitHandler);
fishsanityOnActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(Rando::Fishsanity::OnFlagSetHandler);
fishsanityOnActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>(Rando::Fishsanity::OnActorUpdateHandler);
fishsanityOnActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(Rando::Fishsanity::OnSceneInitHandler);
fishsanityOnActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(Rando::Fishsanity::OnVanillaBehaviorHandler);
}
}); });
} }

View File

@ -353,6 +353,18 @@ Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQu
return { rc, quest_, RCTYPE_GOSSIP_STONE, GetAreaFromScene(scene_), ACTOR_EN_GS, scene_, actorParams_, std::move(shortName_), RHT_NONE, RG_NONE, false }; return { rc, quest_, RCTYPE_GOSSIP_STONE, GetAreaFromScene(scene_), ACTOR_EN_GS, scene_, actorParams_, std::move(shortName_), RHT_NONE, RG_NONE, false };
} }
Rando::Location Rando::Location::Fish(RandomizerCheck rc, RandomizerCheckQuest quest_, ActorID actorId_, SceneID scene_, int32_t actorParams_, RandomizerInf flag_,
std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem) {
return {rc, quest_, RCTYPE_FISH, GetAreaFromScene(scene_), actorId_, scene_, actorParams_, std::move(shortName_), hintKey, vanillaItem, false,
SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, scene_, flag_)};
}
Rando::Location Rando::Location::GrottoFish(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, int32_t actorParams_, RandomizerInf flag_,
std::string&& shortName_, RandomizerHintTextKey hintKey) {
return {rc, quest_, RCTYPE_FISH, area_, ACTOR_EN_FISH, SCENE_GROTTOS, actorParams_, std::move(shortName_), hintKey, RG_FISH, false,
SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, SCENE_GROTTOS, flag_)};
}
Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, std::string&& shortName_) { Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, std::string&& shortName_) {
return { rc, quest_, RCTYPE_GOSSIP_STONE, area_, ACTOR_EN_GS, scene_, actorParams_, std::move(shortName_), RHT_NONE, RG_NONE, false }; return { rc, quest_, RCTYPE_GOSSIP_STONE, area_, ACTOR_EN_GS, scene_, actorParams_, std::move(shortName_), RHT_NONE, RG_NONE, false };
} }

View File

@ -160,6 +160,12 @@ class Location {
static Location GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, uint8_t flag_, static Location GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, uint8_t flag_,
std::string&& shortName_, RandomizerHintTextKey hintKey, uint8_t skullScene_); std::string&& shortName_, RandomizerHintTextKey hintKey, uint8_t skullScene_);
static Location Fish(RandomizerCheck rc, RandomizerCheckQuest quest_, ActorID actorId_, SceneID scene_, int32_t actorParams_,
RandomizerInf flag_, std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem);
static Location GrottoFish(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, int32_t actorParams_,
RandomizerInf flag_, std::string&& shortName_, RandomizerHintTextKey hintKey);
static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, ActorID actorId_, SceneID scene_, std::string&& shortName_, static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, ActorID actorId_, SceneID scene_, std::string&& shortName_,
std::string&& spoilerName_); std::string&& spoilerName_);

View File

@ -948,56 +948,55 @@ void Rando::StaticData::InitLocationTable() { //
+--------------+ */ +--------------+ */
// Fishing Pond // Fishing Pond
locationTable[RC_LH_CHILD_FISH_1] = Location::Base(RC_LH_CHILD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 100, "Child Pond Fish 1", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_1] = Location::Fish(RC_LH_CHILD_FISH_1, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 100, RAND_INF_CHILD_FISH_1, "Child Pond Fish 1", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_2] = Location::Base(RC_LH_CHILD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 101, "Child Pond Fish 2", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_2] = Location::Fish(RC_LH_CHILD_FISH_2, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 101, RAND_INF_CHILD_FISH_2, "Child Pond Fish 2", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_3] = Location::Base(RC_LH_CHILD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 102, "Child Pond Fish 3", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_3] = Location::Fish(RC_LH_CHILD_FISH_3, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 102, RAND_INF_CHILD_FISH_3, "Child Pond Fish 3", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_4] = Location::Base(RC_LH_CHILD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 103, "Child Pond Fish 4", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_4] = Location::Fish(RC_LH_CHILD_FISH_4, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 103, RAND_INF_CHILD_FISH_4, "Child Pond Fish 4", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_5] = Location::Base(RC_LH_CHILD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 104, "Child Pond Fish 5", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_5] = Location::Fish(RC_LH_CHILD_FISH_5, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 104, RAND_INF_CHILD_FISH_5, "Child Pond Fish 5", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_6] = Location::Base(RC_LH_CHILD_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 105, "Child Pond Fish 6", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_6] = Location::Fish(RC_LH_CHILD_FISH_6, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 105, RAND_INF_CHILD_FISH_6, "Child Pond Fish 6", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_7] = Location::Base(RC_LH_CHILD_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 106, "Child Pond Fish 7", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_7] = Location::Fish(RC_LH_CHILD_FISH_7, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 106, RAND_INF_CHILD_FISH_7, "Child Pond Fish 7", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_8] = Location::Base(RC_LH_CHILD_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 107, "Child Pond Fish 8", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_8] = Location::Fish(RC_LH_CHILD_FISH_8, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 107, RAND_INF_CHILD_FISH_8, "Child Pond Fish 8", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_9] = Location::Base(RC_LH_CHILD_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 108, "Child Pond Fish 9", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_9] = Location::Fish(RC_LH_CHILD_FISH_9, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 108, RAND_INF_CHILD_FISH_9, "Child Pond Fish 9", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_10] = Location::Base(RC_LH_CHILD_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 109, "Child Pond Fish 10", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_10] = Location::Fish(RC_LH_CHILD_FISH_10, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 109, RAND_INF_CHILD_FISH_10, "Child Pond Fish 10", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_11] = Location::Base(RC_LH_CHILD_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 110, "Child Pond Fish 11", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_11] = Location::Fish(RC_LH_CHILD_FISH_11, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 110, RAND_INF_CHILD_FISH_11, "Child Pond Fish 11", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_12] = Location::Base(RC_LH_CHILD_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 111, "Child Pond Fish 12", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_12] = Location::Fish(RC_LH_CHILD_FISH_12, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 111, RAND_INF_CHILD_FISH_12, "Child Pond Fish 12", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_13] = Location::Base(RC_LH_CHILD_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 112, "Child Pond Fish 13", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_13] = Location::Fish(RC_LH_CHILD_FISH_13, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 112, RAND_INF_CHILD_FISH_13, "Child Pond Fish 13", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_14] = Location::Base(RC_LH_CHILD_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 113, "Child Pond Fish 14", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_14] = Location::Fish(RC_LH_CHILD_FISH_14, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 113, RAND_INF_CHILD_FISH_14, "Child Pond Fish 14", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_FISH_15] = Location::Base(RC_LH_CHILD_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 114, "Child Pond Fish 15", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_CHILD_FISH_15] = Location::Fish(RC_LH_CHILD_FISH_15, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 114, RAND_INF_CHILD_FISH_15, "Child Pond Fish 15", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_CHILD_LOACH_1] = Location::Base(RC_LH_CHILD_LOACH_1, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 115, "Child Pond Loach 1", RHT_LH_HYRULE_LOACH, RG_NONE); locationTable[RC_LH_CHILD_LOACH_1] = Location::Fish(RC_LH_CHILD_LOACH_1, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 115, RAND_INF_CHILD_LOACH_1, "Child Pond Loach 1", RHT_LH_HYRULE_LOACH, RG_NONE);
locationTable[RC_LH_CHILD_LOACH_2] = Location::Base(RC_LH_CHILD_LOACH_2, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 116, "Child Pond Loach 2", RHT_LH_HYRULE_LOACH, RG_NONE); locationTable[RC_LH_CHILD_LOACH_2] = Location::Fish(RC_LH_CHILD_LOACH_2, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 116, RAND_INF_CHILD_LOACH_2, "Child Pond Loach 2", RHT_LH_HYRULE_LOACH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_1] = Location::Base(RC_LH_ADULT_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 100, "Adult Pond Fish 1", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_1] = Location::Fish(RC_LH_ADULT_FISH_1, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 100, RAND_INF_ADULT_FISH_1, "Adult Pond Fish 1", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_2] = Location::Base(RC_LH_ADULT_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 101, "Adult Pond Fish 2", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_2] = Location::Fish(RC_LH_ADULT_FISH_2, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 101, RAND_INF_ADULT_FISH_2, "Adult Pond Fish 2", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_3] = Location::Base(RC_LH_ADULT_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 102, "Adult Pond Fish 3", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_3] = Location::Fish(RC_LH_ADULT_FISH_3, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 102, RAND_INF_ADULT_FISH_3, "Adult Pond Fish 3", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_4] = Location::Base(RC_LH_ADULT_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 103, "Adult Pond Fish 4", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_4] = Location::Fish(RC_LH_ADULT_FISH_4, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 103, RAND_INF_ADULT_FISH_4, "Adult Pond Fish 4", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_5] = Location::Base(RC_LH_ADULT_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 104, "Adult Pond Fish 5", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_5] = Location::Fish(RC_LH_ADULT_FISH_5, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 104, RAND_INF_ADULT_FISH_5, "Adult Pond Fish 5", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_6] = Location::Base(RC_LH_ADULT_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 105, "Adult Pond Fish 6", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_6] = Location::Fish(RC_LH_ADULT_FISH_6, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 105, RAND_INF_ADULT_FISH_6, "Adult Pond Fish 6", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_7] = Location::Base(RC_LH_ADULT_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 106, "Adult Pond Fish 7", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_7] = Location::Fish(RC_LH_ADULT_FISH_7, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 106, RAND_INF_ADULT_FISH_7, "Adult Pond Fish 7", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_8] = Location::Base(RC_LH_ADULT_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 107, "Adult Pond Fish 8", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_8] = Location::Fish(RC_LH_ADULT_FISH_8, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 107, RAND_INF_ADULT_FISH_8, "Adult Pond Fish 8", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_9] = Location::Base(RC_LH_ADULT_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 108, "Adult Pond Fish 9", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_9] = Location::Fish(RC_LH_ADULT_FISH_9, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 108, RAND_INF_ADULT_FISH_9, "Adult Pond Fish 9", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_10] = Location::Base(RC_LH_ADULT_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 109, "Adult Pond Fish 10", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_10] = Location::Fish(RC_LH_ADULT_FISH_10, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 109, RAND_INF_ADULT_FISH_10, "Adult Pond Fish 10", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_11] = Location::Base(RC_LH_ADULT_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 110, "Adult Pond Fish 11", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_11] = Location::Fish(RC_LH_ADULT_FISH_11, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 110, RAND_INF_ADULT_FISH_11, "Adult Pond Fish 11", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_12] = Location::Base(RC_LH_ADULT_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 111, "Adult Pond Fish 12", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_12] = Location::Fish(RC_LH_ADULT_FISH_12, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 111, RAND_INF_ADULT_FISH_12, "Adult Pond Fish 12", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_13] = Location::Base(RC_LH_ADULT_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 112, "Adult Pond Fish 13", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_13] = Location::Fish(RC_LH_ADULT_FISH_13, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 112, RAND_INF_ADULT_FISH_13, "Adult Pond Fish 13", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_14] = Location::Base(RC_LH_ADULT_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 113, "Adult Pond Fish 14", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_14] = Location::Fish(RC_LH_ADULT_FISH_14, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 113, RAND_INF_ADULT_FISH_14, "Adult Pond Fish 14", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_FISH_15] = Location::Base(RC_LH_ADULT_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 114, "Adult Pond Fish 15", RHT_LH_POND_FISH, RG_NONE); locationTable[RC_LH_ADULT_FISH_15] = Location::Fish(RC_LH_ADULT_FISH_15, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 114, RAND_INF_ADULT_FISH_15, "Adult Pond Fish 15", RHT_LH_POND_FISH, RG_NONE);
locationTable[RC_LH_ADULT_LOACH] = Location::Base(RC_LH_ADULT_LOACH, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_FISHING, SCENE_FISHING_POND, 115, "Adult Pond Loach", RHT_LH_HYRULE_LOACH, RG_NONE); locationTable[RC_LH_ADULT_LOACH] = Location::Fish(RC_LH_ADULT_LOACH, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, 115, RAND_INF_ADULT_LOACH, "Adult Pond Loach", RHT_LH_HYRULE_LOACH, RG_NONE);
// Grotto fish // Grotto fish
locationTable[RC_KF_STORMS_GROTTO_FISH] = Location::Base(RC_KF_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KOKIRI_FOREST, ACTOR_EN_FISH, SCENE_GROTTOS, 1, "Storms Grotto Fish", RHT_KF_STORMS_GROTTO_FISH, RG_FISH); locationTable[RC_KF_STORMS_GROTTO_FISH] = Location::GrottoFish(RC_KF_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, 0x12C, RAND_INF_GROTTO_FISH_KF_STORMS_GROTTO, "Storms Grotto Fish", RHT_KF_STORMS_GROTTO_FISH);
locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_FISH] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LOST_WOODS, ACTOR_EN_FISH, SCENE_GROTTOS, 1, "Near Shortcuts Grotto Fish", RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH, RG_FISH); locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_FISH] = Location::GrottoFish(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RCQUEST_BOTH, RCAREA_LOST_WOODS, 0x114, RAND_INF_GROTTO_FISH_LW_NEAR_SHORTCUTS_GROTTO, "Near Shortcuts Grotto Fish", RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH);
locationTable[RC_HF_SOUTHEAST_GROTTO_FISH] = Location::Base(RC_HF_SOUTHEAST_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, "Southeast Grotto Fish", RHT_HF_SOUTHEAST_GROTTO_FISH, RG_FISH); locationTable[RC_HF_SOUTHEAST_GROTTO_FISH] = Location::GrottoFish(RC_HF_SOUTHEAST_GROTTO_FISH, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, 0x122, RAND_INF_GROTTO_FISH_HF_SOUTHEAST_GROTTO, "Southeast Grotto Fish", RHT_HF_SOUTHEAST_GROTTO_FISH);
locationTable[RC_HF_OPEN_GROTTO_FISH] = Location::Base(RC_HF_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, "Open Grotto Fish", RHT_HF_OPEN_GROTTO_FISH, RG_FISH); locationTable[RC_HF_OPEN_GROTTO_FISH] = Location::GrottoFish(RC_HF_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, 0x103, RAND_INF_GROTTO_FISH_HF_OPEN_GROTTO, "Open Grotto Fish", RHT_HF_OPEN_GROTTO_FISH);
locationTable[RC_HF_NEAR_MARKET_GROTTO_FISH] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, "Near Market Grotto Fish", RHT_HF_NEAR_MARKET_GROTTO_FISH, RG_FISH); locationTable[RC_HF_NEAR_MARKET_GROTTO_FISH] = Location::GrottoFish(RC_HF_NEAR_MARKET_GROTTO_FISH, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, 0x100, RAND_INF_GROTTO_FISH_HF_NEAR_MARKET_GROTTO, "Near Market Grotto Fish", RHT_HF_NEAR_MARKET_GROTTO_FISH);
locationTable[RC_KAK_OPEN_GROTTO_FISH] = Location::Base(RC_KAK_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_FISH, SCENE_GROTTOS, 1, "Open Grotto Fish", RHT_KAK_OPEN_GROTTO_FISH, RG_FISH); locationTable[RC_KAK_OPEN_GROTTO_FISH] = Location::GrottoFish(RC_KAK_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, 0x128, RAND_INF_GROTTO_FISH_KAK_OPEN_GROTTO, "Open Grotto Fish", RHT_KAK_OPEN_GROTTO_FISH);
locationTable[RC_DMT_STORMS_GROTTO_FISH] = Location::Base(RC_DMT_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_FISH, SCENE_GROTTOS, 1, "Storms Grotto Fish", RHT_DMT_STORMS_GROTTO_FISH, RG_FISH); locationTable[RC_DMT_STORMS_GROTTO_FISH] = Location::GrottoFish(RC_DMT_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, 0x157, RAND_INF_GROTTO_FISH_DMT_STORMS_GROTTO, "Storms Grotto Fish", RHT_DMT_STORMS_GROTTO_FISH);
locationTable[RC_DMC_UPPER_GROTTO_FISH] = Location::Base(RC_DMC_UPPER_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, "Upper Grotto Fish", RHT_DMC_UPPER_GROTTO_FISH, RG_FISH); locationTable[RC_DMC_UPPER_GROTTO_FISH] = Location::GrottoFish(RC_DMC_UPPER_GROTTO_FISH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, 0x17A, RAND_INF_GROTTO_FISH_DMC_UPPER_GROTTO, "Upper Grotto Fish", RHT_DMC_UPPER_GROTTO_FISH);
locationTable[RC_ZR_OPEN_GROTTO_FISH] = Location::Base(RC_ZR_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_RIVER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, "Open Grotto Fish", RHT_ZR_OPEN_GROTTO_FISH, RG_FISH); locationTable[RC_ZR_OPEN_GROTTO_FISH] = Location::GrottoFish(RC_ZR_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, 0x129, RAND_INF_GROTTO_FISH_ZR_OPEN_GROTTO, "Open Grotto Fish", RHT_ZR_OPEN_GROTTO_FISH);
// Zora's Domain fish // Zora's Domain fish
locationTable[RC_ZD_FISH_1] = Location::Base(RC_ZD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 0, "Fish 1", RHT_ZD_FISH, RG_FISH); locationTable[RC_ZD_FISH_1] = Location::Fish(RC_ZD_FISH_1, RCQUEST_BOTH, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 0, RAND_INF_ZD_FISH_1, "Fish 1", RHT_ZD_FISH, RG_FISH);
locationTable[RC_ZD_FISH_2] = Location::Base(RC_ZD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 1, "Fish 2", RHT_ZD_FISH, RG_FISH); locationTable[RC_ZD_FISH_2] = Location::Fish(RC_ZD_FISH_2, RCQUEST_BOTH, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 1, RAND_INF_ZD_FISH_2, "Fish 2", RHT_ZD_FISH, RG_FISH);
locationTable[RC_ZD_FISH_3] = Location::Base(RC_ZD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 2, "Fish 3", RHT_ZD_FISH, RG_FISH); locationTable[RC_ZD_FISH_3] = Location::Fish(RC_ZD_FISH_3, RCQUEST_BOTH, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 2, RAND_INF_ZD_FISH_3, "Fish 3", RHT_ZD_FISH, RG_FISH);
locationTable[RC_ZD_FISH_4] = Location::Base(RC_ZD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 3, "Fish 4", RHT_ZD_FISH, RG_FISH); locationTable[RC_ZD_FISH_4] = Location::Fish(RC_ZD_FISH_4, RCQUEST_BOTH, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 3, RAND_INF_ZD_FISH_4, "Fish 4", RHT_ZD_FISH, RG_FISH);
locationTable[RC_ZD_FISH_5] = Location::Base(RC_ZD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 4, "Fish 5", RHT_ZD_FISH, RG_FISH); locationTable[RC_ZD_FISH_5] = Location::Fish(RC_ZD_FISH_5, RCQUEST_BOTH, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 4, RAND_INF_ZD_FISH_5, "Fish 5", RHT_ZD_FISH, RG_FISH);
// Gossip Stones // Gossip Stones
locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, SCENE_DEATH_MOUNTAIN_CRATER, 14341, "Gossip Stone"); locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, SCENE_DEATH_MOUNTAIN_CRATER, 14341, "Gossip Stone");

View File

@ -1074,15 +1074,6 @@ Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum,
specialRc = RC_DODONGOS_CAVERN_GOSSIP_STONE; specialRc = RC_DODONGOS_CAVERN_GOSSIP_STONE;
} }
break; break;
case SCENE_GROTTOS:
// Grotto fish are identified by respawn data
if (actorId == ACTOR_EN_FISH && actorParams == 1) {
int8_t data = gSaveContext.respawn[RESPAWN_MODE_RETURN].data;
if (Rando::StaticData::randomizerGrottoFishMap.contains(data)) {
specialRc = Rando::StaticData::randomizerGrottoFishMap[data];
}
}
break;
} }
if (specialRc != RC_UNKNOWN_CHECK) { if (specialRc != RC_UNKNOWN_CHECK) {

View File

@ -7,7 +7,6 @@
#include "z_en_fish.h" #include "z_en_fish.h"
#include "objects/gameplay_keep/gameplay_keep.h" #include "objects/gameplay_keep/gameplay_keep.h"
#include "vt.h" #include "vt.h"
#include "soh/Enhancements/randomizer/fishsanity.h"
#define FLAGS 0 #define FLAGS 0
@ -37,7 +36,6 @@ void EnFish_Unique_SwimIdle(EnFish* this, PlayState* play);
static Actor* D_80A17010 = NULL; static Actor* D_80A17010 = NULL;
static f32 D_80A17014 = 0.0f; static f32 D_80A17014 = 0.0f;
static f32 D_80A17018 = 0.0f; static f32 D_80A17018 = 0.0f;
static Color_RGBA16 fsPulseColor = { 30, 240, 200 };
static ColliderJntSphElementInit sJntSphElementsInit[1] = { static ColliderJntSphElementInit sJntSphElementsInit[1] = {
{ {
@ -762,31 +760,10 @@ void EnFish_Update(Actor* thisx, PlayState* play) {
} }
} }
// #region SOH [Randomizer]
s32 EnFish_FishsanityOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
void* thisx) {
EnFish* this = (EnFish*)thisx;
Fishsanity_OpenGreyscaleColor(play, &fsPulseColor, ABS(this->actor.params) * 20);
return 0;
}
void EnFish_FishPostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
Fishsanity_CloseGreyscaleColor(play);
}
// #endregion
void EnFish_Draw(Actor* thisx, PlayState* play) { void EnFish_Draw(Actor* thisx, PlayState* play) {
EnFish* this = (EnFish*)thisx; EnFish* this = (EnFish*)thisx;
Gfx_SetupDL_25Opa(play->state.gfxCtx); Gfx_SetupDL_25Opa(play->state.gfxCtx);
// #region SOH [Randomizer]
// Modify drawing for uncollected fish, having a shadowDraw implies this is being given uncollected FX
if (IS_RANDO && Randomizer_GetOverworldFishShuffled() && this->actor.shape.shadowDraw != NULL) {
SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnFish_FishsanityOverrideLimbDraw, EnFish_FishPostLimbDraw, this);
Collider_UpdateSpheres(0, &this->collider);
return;
}
// #endregion
SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, NULL, NULL); SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, NULL, NULL);
Collider_UpdateSpheres(0, &this->collider); Collider_UpdateSpheres(0, &this->collider);
} }

View File

@ -15,8 +15,6 @@
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
#define WATER_SURFACE_Y(play) play->colCtx.colHeader->waterBoxes->ySurface #define WATER_SURFACE_Y(play) play->colCtx.colHeader->waterBoxes->ySurface
#define IS_FISHSANITY (IS_RANDO && Randomizer_GetPondFishShuffled())
#define FISHID(params) (Randomizer_IdentifyFish(play->sceneNum, params))
bool getShouldSpawnLoaches(); bool getShouldSpawnLoaches();
void Fishing_Init(Actor* thisx, PlayState* play); void Fishing_Init(Actor* thisx, PlayState* play);
@ -433,7 +431,6 @@ static f32 sFishGroupAngle3;
static FishingEffect sFishingEffects[FISHING_EFFECT_COUNT]; static FishingEffect sFishingEffects[FISHING_EFFECT_COUNT];
static Vec3f sStreamSoundProjectedPos; static Vec3f sStreamSoundProjectedPos;
static s16 sFishOnHandParams; static s16 sFishOnHandParams;
static Color_RGBA16 fsPulseColor = { 30, 240, 200 };
u8 AllHyruleLoaches() { u8 AllHyruleLoaches() {
return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("AllHyruleLoaches"), 0); return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("AllHyruleLoaches"), 0);
@ -3998,9 +3995,6 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
sFishOnHandLength = this->fishLength; sFishOnHandLength = this->fishLength;
sFishOnHandIsLoach = (this->isLoach || AllHyruleLoaches()); sFishOnHandIsLoach = (this->isLoach || AllHyruleLoaches());
sLureCaughtWith = sLureEquipped; sLureCaughtWith = sLureEquipped;
if (IS_FISHSANITY) {
sFishOnHandParams = this->fishsanityParams;
}
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
} else if (getShouldConfirmKeep() && (this->isLoach == 0 && !AllHyruleLoaches()) && (sFishOnHandIsLoach == 0) && } else if (getShouldConfirmKeep() && (this->isLoach == 0 && !AllHyruleLoaches()) && (sFishOnHandIsLoach == 0) &&
((s16)this->fishLength < (s16)sFishOnHandLength)) { ((s16)this->fishLength < (s16)sFishOnHandLength)) {
@ -4015,11 +4009,6 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
sLureCaughtWith = sLureEquipped; sLureCaughtWith = sLureEquipped;
this->fishLength = lengthTemp; this->fishLength = lengthTemp;
this->isLoach = loachTemp; this->isLoach = loachTemp;
if (IS_FISHSANITY) {
s16 paramsTemp = sFishOnHandParams;
sFishOnHandParams = this->fishsanityParams;
this->fishsanityParams = paramsTemp;
}
} }
} }
if (this->keepState == 0) { if (this->keepState == 0) {
@ -4040,11 +4029,6 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
sLureCaughtWith = sLureEquipped; sLureCaughtWith = sLureEquipped;
this->fishLength = temp1; this->fishLength = temp1;
this->isLoach = temp2; this->isLoach = temp2;
if (IS_FISHSANITY) {
s16 paramsTemp = sFishOnHandParams;
sFishOnHandParams = this->fishsanityParams;
this->fishsanityParams = paramsTemp;
}
} }
sRodCastState = 0; sRodCastState = 0;
} }
@ -4310,13 +4294,6 @@ s32 Fishing_FishOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Ve
void* thisx) { void* thisx) {
Fishing* this = (Fishing*)thisx; Fishing* this = (Fishing*)thisx;
// #region SOH [Randomizer]
// A fish having a shadowDraw implies that it is being given uncollected FX
if (IS_FISHSANITY && this->actor.shape.shadowDraw != NULL) {
Fishsanity_OpenGreyscaleColor(play, &fsPulseColor, (this->actor.params - 100) * 20);
}
// #endregion
if (limbIndex == 0xD) { if (limbIndex == 0xD) {
rot->z -= this->fishLimbDRotZDelta - 11000; rot->z -= this->fishLimbDRotZDelta - 11000;
} else if ((limbIndex == 2) || (limbIndex == 3)) { } else if ((limbIndex == 2) || (limbIndex == 3)) {
@ -4339,13 +4316,6 @@ s32 Fishing_FishOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Ve
void Fishing_FishPostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { void Fishing_FishPostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
Fishing* this = (Fishing*)thisx; Fishing* this = (Fishing*)thisx;
// #region SOH [Randomizer]
// A fish having a shadowDraw implies that it is being given uncollected FX
if (IS_FISHSANITY && this->actor.shape.shadowDraw != NULL) {
Fishsanity_CloseGreyscaleColor(play);
}
// #endregion
if (limbIndex == 0xD) { if (limbIndex == 0xD) {
Matrix_MultVec3f(&sFishMouthOffset, &this->fishMouthPos); Matrix_MultVec3f(&sFishMouthOffset, &this->fishMouthPos);
} }
@ -4355,13 +4325,6 @@ s32 Fishing_LoachOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, V
void* thisx) { void* thisx) {
Fishing* this = (Fishing*)thisx; Fishing* this = (Fishing*)thisx;
// #region SOH [Randomizer]
// A fish having a shadowDraw implies that it is being given uncollected FX
if (IS_FISHSANITY && this->actor.shape.shadowDraw != NULL) {
Fishsanity_OpenGreyscaleColor(play, &fsPulseColor, (this->actor.params - 100) * 20);
}
// #endregion
if (limbIndex == 3) { if (limbIndex == 3) {
rot->y += this->loachRotYDelta[0]; rot->y += this->loachRotYDelta[0];
} else if (limbIndex == 4) { } else if (limbIndex == 4) {
@ -4377,13 +4340,6 @@ void Fishing_LoachPostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3
static Vec3f sLoachMouthOffset = { 500.0f, 500.0f, 0.0f }; static Vec3f sLoachMouthOffset = { 500.0f, 500.0f, 0.0f };
Fishing* this = (Fishing*)thisx; Fishing* this = (Fishing*)thisx;
// #region SOH [Randomizer]
// A fish having a shadowDraw implies that it is being given uncollected FX
if (IS_FISHSANITY && this->actor.shape.shadowDraw != NULL) {
Fishsanity_CloseGreyscaleColor(play);
}
// #endregion
if (limbIndex == 0xB) { if (limbIndex == 0xB) {
Matrix_MultVec3f(&sLoachMouthOffset, &this->fishMouthPos); Matrix_MultVec3f(&sLoachMouthOffset, &this->fishMouthPos);
} }

View File

@ -57,7 +57,6 @@ typedef struct Fishing {
/* 0x0220 */ LightInfo lightInfo; /* 0x0220 */ LightInfo lightInfo;
/* 0x0230 */ ColliderJntSph collider; /* 0x0230 */ ColliderJntSph collider;
/* 0x0250 */ ColliderJntSphElement colliderElements[12]; /* 0x0250 */ ColliderJntSphElement colliderElements[12];
/* */ s16 fishsanityParams;
} Fishing; // size = 0x0550 } Fishing; // size = 0x0550
#define EN_FISH_OWNER 1 // param for owner of pond. default if params<100 #define EN_FISH_OWNER 1 // param for owner of pond. default if params<100

View File

@ -29,7 +29,6 @@
#include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/Enhancements/randomizer/randomizer_grotto.h" #include "soh/Enhancements/randomizer/randomizer_grotto.h"
#include "soh/Enhancements/randomizer/fishsanity.h"
#include "soh/frame_interpolation.h" #include "soh/frame_interpolation.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
@ -13955,33 +13954,9 @@ void Player_Action_8084ECA4(Player* this, PlayState* play) {
func_8083721C(this); func_8083721C(this);
// TODO: Rework the bottle rando code in vanilla behavior overhaul
if (LinkAnimation_Update(play, &this->skelAnime)) { if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->av1.actionVar1 != 0) { if (this->av1.actionVar1 != 0) {
if (IS_RANDO && this->av1.actionVar1 < 0) { if (this->av2.actionVar2 == 0) {
rc = this->av2.actionVar2;
// Award rando item; this should only give us GI_NONE if something went wrong during the catch setup
gi = Randomizer_GetItemFromKnownCheck(rc, GI_NONE);
temp = Randomizer_GetRandomizerInfFromCheck(rc);
// Either we can't give an item, we can't tell if we've gotten the check, or we have definitely gotten the check
if (gi.getItemId == GI_NONE || temp == RAND_INF_MAX || Flags_GetRandomizerInf(temp)) {
this->av1.actionVar1 = 0;
if (this->interactRangeActor != NULL)
this->interactRangeActor->parent = NULL;
}
// Item get cutscene hasn't played yet
else if((this->interactRangeActor == NULL && !(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) || !Actor_HasParent(this->interactRangeActor, play)) {
// Can't guarantee that whatever we "caught" is actually going to still exist
if (GiveItemEntryWithoutActor(play, gi)) {
// have to set this flag manually to prevent interactRangeActor from being wiped out
this->stateFlags1 |= PLAYER_STATE1_ITEM_OVER_HEAD;
this->pendingFlag.flagID = temp;
this->pendingFlag.flagType = FLAG_RANDOMIZER_INF;
Flags_SetRandomizerInf(temp);
}
}
} else if (this->av2.actionVar2 == 0) {
if (CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) { if (CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) {
this->av1.actionVar1 = 0; this->av1.actionVar1 = 0;
} else { } else {
@ -14017,42 +13992,15 @@ void Player_Action_8084ECA4(Player* this, PlayState* play) {
} }
} }
if (i < 4) { if (GameInteractor_Should(VB_BOTTLE_ACTOR, i < 4, this->interactRangeActor)) {
this->av1.actionVar1 = i + 1; this->av1.actionVar1 = i + 1;
this->av2.actionVar2 = 0; this->av2.actionVar2 = 0;
this->interactRangeActor->parent = &this->actor; this->interactRangeActor->parent = &this->actor;
// TODO: this should probably be refactored a bit, maybe rehome some of this to rando instead Player_UpdateBottleHeld(play, this, catchInfo->itemId, ABS(catchInfo->itemAction));
if (IS_RANDO) { if (!CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) {
// Check if fishsanity applies for this actor this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
if (Randomizer_GetOverworldFishShuffled()) { Player_AnimPlayOnceAdjusted(play, this, sp24->unk_04);
fish = Randomizer_IdentifyFish(play->sceneNum, this->interactRangeActor->params); func_80835EA4(play, 4);
if (fish.randomizerCheck != RC_UNKNOWN_CHECK && !Flags_GetRandomizerInf(fish.randomizerInf)) {
gi = Randomizer_GetItemFromKnownCheck(fish.randomizerCheck, GI_FISH);
rc = fish.randomizerCheck;
// check if the item is a bottle item anyway
catchInfo = NULL;
for (j = 0; j < 4; j++) {
if (D_80854A04[j].itemId == gi.itemId) {
catchInfo = &D_80854A04[j];
break;
}
}
}
}
}
// Vanilla behavior/rando gave a bottle item
if (!IS_RANDO || catchInfo != NULL) {
Player_UpdateBottleHeld(play, this, catchInfo->itemId, ABS(catchInfo->itemAction));
if (!CVarGetInteger(CVAR_ENHANCEMENT("FastDrops"), 0)) {
this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
Player_AnimPlayOnceAdjusted(play, this, sp24->unk_04);
func_80835EA4(play, 4);
}
} else if (IS_RANDO && gi.itemId != ITEM_NONE) {
// Non-bottle item found from rando, flag for special behavior
this->av1.actionVar1 = -1;
this->av2.actionVar2 = rc;
} }
} }
} }