mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-08-27 00:44:04 -04:00
Hookify fish, refactor fishsanity (#7091)
This commit is contained in:
@@ -322,9 +322,9 @@ extern GraphicsContext* __gfxCtx;
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(rsk) \
|
||||
(OTRGlobals::Instance->gRandoContext->GetOption(rsk).IsNot(RO_DUNGEON_ITEM_LOC_STARTWITH) && \
|
||||
OTRGlobals::Instance->gRandoContext->GetOption(rsk).IsNot(RO_DUNGEON_ITEM_LOC_VANILLA) && \
|
||||
OTRGlobals::Instance->gRandoContext->GetOption(rsk).IsNot(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON))
|
||||
(RAND_GET_OPTION(rsk).IsNot(RO_DUNGEON_ITEM_LOC_STARTWITH) && \
|
||||
RAND_GET_OPTION(rsk).IsNot(RO_DUNGEON_ITEM_LOC_VANILLA) && \
|
||||
RAND_GET_OPTION(rsk).IsNot(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON))
|
||||
#endif
|
||||
// #endregion
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "soh/ShipUtils.h"
|
||||
#include "soh/Enhancements/randomizer/SeedContext.h"
|
||||
#include "soh/Enhancements/enhancementTypes.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
#include "variables.h"
|
||||
#include "soh/ResourceManagerHelpers.h"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include <cmath>
|
||||
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "src/overlays/actors/ovl_Fishing/z_fishing.h"
|
||||
@@ -8,7 +10,14 @@ extern "C" {
|
||||
#include <macros.h>
|
||||
extern PlayState* gPlayState;
|
||||
extern SaveContext gSaveContext;
|
||||
f32 Fishing_GetMinimumRequiredScore();
|
||||
}
|
||||
|
||||
// RANDOTODO: update the enhancement sliders to not allow
|
||||
// values above rando fish weight values when rando'd
|
||||
static float Fishing_GetMinimumRequiredScore() {
|
||||
int weight = LINK_IS_CHILD ? CVarGetInteger(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 10)
|
||||
: CVarGetInteger(CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 13);
|
||||
return sqrtf((weight - 0.5f) / 0.0036f);
|
||||
}
|
||||
|
||||
void BuildFishingMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
||||
@@ -29,6 +38,37 @@ void RegisterFishingMessages() {
|
||||
});
|
||||
}
|
||||
|
||||
void RegisterCustomizeFishing() {
|
||||
bool customized = CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0);
|
||||
|
||||
COND_VB_SHOULD(VB_FISHING_USE_DEFAULT_RECORD_LENGTH, customized, {
|
||||
f32* recordLength = va_arg(args, f32*);
|
||||
*recordLength = Fishing_GetMinimumRequiredScore();
|
||||
*should = false;
|
||||
});
|
||||
|
||||
COND_VB_SHOULD(VB_FISHING_SPAWN_LOACHES, (customized && CVarGetInteger(CVAR_ENHANCEMENT("LoachesAlwaysAppear"), 0)),
|
||||
{ *should = true; });
|
||||
|
||||
COND_VB_SHOULD(VB_FISHING_FISH_IS_LOACH, (customized && CVarGetInteger(CVAR_ENHANCEMENT("AllHyruleLoaches"), 0)),
|
||||
{ *should = true; });
|
||||
|
||||
COND_VB_SHOULD(VB_FISHING_FISH_BITE, (customized && CVarGetInteger(CVAR_ENHANCEMENT("GuaranteeFishingBite"), 0)),
|
||||
{ *should = true; });
|
||||
|
||||
COND_VB_SHOULD(VB_FISHING_FISH_ESCAPE, (customized && CVarGetInteger(CVAR_ENHANCEMENT("FishNeverEscape"), 0)),
|
||||
{ *should = false; });
|
||||
|
||||
COND_VB_SHOULD(VB_FISHING_CATCH_FISH, (customized && CVarGetInteger(CVAR_ENHANCEMENT("InstantFishing"), 0)),
|
||||
{ *should = true; });
|
||||
|
||||
COND_VB_SHOULD(VB_FISHING_INSTANT_CATCH, (customized && CVarGetInteger(CVAR_ENHANCEMENT("InstantFishing"), 0)),
|
||||
{ *should = true; });
|
||||
|
||||
COND_VB_SHOULD(VB_FISHING_CONFIRM_KEEPING_SMALLER_FISH,
|
||||
(customized && CVarGetInteger(CVAR_ENHANCEMENT("SkipKeepConfirmation"), 0)), { *should = false; });
|
||||
}
|
||||
|
||||
void RegisterHoverFishing() {
|
||||
COND_VB_SHOULD(VB_NOT_CAST_FISHING, (CVarGetInteger(CVAR_ENHANCEMENT("HoverFishing"), false)), {
|
||||
Vec3f* rodCheckPos = va_arg(args, Vec3f*);
|
||||
@@ -68,6 +108,12 @@ void RegisterAllowFishingBlankB() {
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterFishingMessages, { CVAR_ENHANCEMENT("CustomizeFishing"), "IS_RANDO" });
|
||||
static RegisterShipInitFunc
|
||||
initCustomizeFishing(RegisterCustomizeFishing,
|
||||
{ CVAR_ENHANCEMENT("CustomizeFishing"), CVAR_ENHANCEMENT("LoachesAlwaysAppear"),
|
||||
CVAR_ENHANCEMENT("AllHyruleLoaches"), CVAR_ENHANCEMENT("GuaranteeFishingBite"),
|
||||
CVAR_ENHANCEMENT("FishNeverEscape"), CVAR_ENHANCEMENT("InstantFishing"),
|
||||
CVAR_ENHANCEMENT("SkipKeepConfirmation") });
|
||||
static RegisterShipInitFunc initHoverFishing(RegisterHoverFishing, { CVAR_ENHANCEMENT("HoverFishing") });
|
||||
static RegisterShipInitFunc initAllowFishingBlankB(RegisterAllowFishingBlankB,
|
||||
{ CVAR_ENHANCEMENT("FishingBlankB"), "IS_RANDO" });
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/custom-message/CustomMessageManager.h"
|
||||
#include "soh/Enhancements/custom-message/CustomMessageTypes.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "soh/cvar_prefixes.h"
|
||||
|
||||
extern "C" {
|
||||
#include <variables.h>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/custom-message/CustomMessageManager.h"
|
||||
#include "soh/Enhancements/custom-message/CustomMessageTypes.h"
|
||||
#include "soh/Enhancements/randomizer/SeedContext.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "soh/cvar_prefixes.h"
|
||||
|
||||
extern "C" {
|
||||
#include "variables.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
extern "C" {
|
||||
#include <variables.h>
|
||||
}
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/custom-message/CustomMessageManager.h"
|
||||
#include "soh/Enhancements/custom-message/CustomMessageTypes.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "soh/cvar_prefixes.h"
|
||||
|
||||
// TODO: Port the rest of the behavior for this enhancement here.
|
||||
|
||||
@@ -23,6 +22,9 @@ void BuildQuitFishingMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
||||
void QuitFishingAtDoor_Register() {
|
||||
COND_ID_HOOK(OnOpenText, TEXT_FISHERMAN_LEAVE, CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0),
|
||||
BuildQuitFishingMessage);
|
||||
|
||||
COND_VB_SHOULD(VB_FISHING_QUIT_AT_DOOR, CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0),
|
||||
{ *should = true; });
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(QuitFishingAtDoor_Register, { CVAR_ENHANCEMENT("QuitFishingAtDoor") });
|
||||
@@ -757,6 +757,97 @@ typedef enum {
|
||||
// - `*EnElf`
|
||||
VB_FAIRY_HEAL,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// this->actor.xzDistToPlayer < (KREG(59) + 50.0f)
|
||||
// ```
|
||||
// Whether a hooked fish is reeled in close enough to be caught.
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FISHING_CATCH_FISH,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// (this->isLoach == 0) && (sFishOnHandIsLoach == 0) && ((s16)this->fishLength < (s16)sFishOnHandLength)
|
||||
// ```
|
||||
// Whether keeping a fish smaller than the one held asks for confirmation.
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FISHING_CONFIRM_KEEPING_SMALLER_FISH,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// ((this->timerArray[0] == 1) || (Rand_ZeroOne() < chance)) &&
|
||||
// ((Rand_ZeroOne() < (this->perception * multiplier)) || ((this->isLoach + 1) == KREG(69)))
|
||||
// ```
|
||||
// Whether a fish bites the lure.
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FISHING_FISH_BITE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// ((sLureTimer & 0x7F) == 0) && (Rand_ZeroOne() < 0.05f) && (sLureEquipped != FS_LURE_SINKING) && (KREG(69) == 0)
|
||||
// ```
|
||||
// Whether a hooked fish randomly escapes the line.
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FISHING_FISH_ESCAPE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// sFishInits[thisx->params - EN_FISH_PARAM].isLoach
|
||||
// ```
|
||||
// Whether this pond fish is a loach.
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FISHING_FISH_IS_LOACH,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// false
|
||||
// ```
|
||||
// Whether a caught fish snaps to Link's hand instead of drifting there.
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FISHING_INSTANT_CATCH,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// false
|
||||
// ```
|
||||
// Whether the pond owner offers to quit fishing at the door.
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FISHING_QUIT_AT_DOOR,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// (KREG(1) == 1) || ((sFishGameNumber & 3) == 3)
|
||||
// ```
|
||||
// Whether loaches spawn in the pond this game.
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FISHING_SPAWN_LOACHES,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// Whether the starting fishing record uses the vanilla length.
|
||||
// A hook returning false should write its own length through the arg.
|
||||
// #### `args`
|
||||
// - `*f32` (sFishingRecordLength)
|
||||
VB_FISHING_USE_DEFAULT_RECORD_LENGTH,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FISHING_ZERO_XZ,
|
||||
|
||||
// #### `result`
|
||||
// True if the next text position must be beyond the current position; false otherwise
|
||||
// #### `args`
|
||||
@@ -2653,14 +2744,6 @@ typedef enum {
|
||||
// - `*Vec3f`
|
||||
VB_NOT_CAST_FISHING,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FISHING_ZERO_XZ,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// false
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "playthrough.hpp"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <libultraship/bridge/consolevariablebridge.h>
|
||||
|
||||
#include "playthrough.hpp"
|
||||
#include "fill.hpp"
|
||||
#include "../location_access.h"
|
||||
#include "../rng.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "src/overlays/actors/ovl_En_GirlA/z_en_girla.h"
|
||||
#include "soh/Enhancements/randomizer/SeedContext.h"
|
||||
@@ -21,7 +21,7 @@ void RegisterVBOverrides() {
|
||||
}
|
||||
int8_t capacity = 50;
|
||||
if (bombchuBag.Is(RO_BOMBCHU_BAG_PROGRESSIVE)) {
|
||||
capacity = OTRGlobals::Instance->gRandoContext->GetBombchuCapacity();
|
||||
capacity = Rando::Context::GetInstance()->GetBombchuCapacity();
|
||||
}
|
||||
if (AMMO(ITEM_BOMBCHU) >= capacity) {
|
||||
*canBuy = CANBUY_RESULT_CANT_GET_NOW;
|
||||
@@ -31,7 +31,7 @@ void RegisterVBOverrides() {
|
||||
|
||||
COND_VB_SHOULD(VB_CHECK_BOMBCHU_CAPACITY, shouldRegister, {
|
||||
*should = false;
|
||||
uint8_t capacity = OTRGlobals::Instance->gRandoContext->GetBombchuCapacity();
|
||||
uint8_t capacity = Rando::Context::GetInstance()->GetBombchuCapacity();
|
||||
if (AMMO(ITEM_BOMBCHU) > capacity) {
|
||||
AMMO(ITEM_BOMBCHU) = capacity;
|
||||
}
|
||||
@@ -40,7 +40,7 @@ void RegisterVBOverrides() {
|
||||
COND_VB_SHOULD(VB_COLOR_AMMO_GREEN, shouldRegister, {
|
||||
int16_t i = va_arg(args, int);
|
||||
if (i == ITEM_BOMBCHU) {
|
||||
uint8_t capacity = OTRGlobals::Instance->gRandoContext->GetBombchuCapacity();
|
||||
uint8_t capacity = Rando::Context::GetInstance()->GetBombchuCapacity();
|
||||
if (AMMO(i) == capacity) {
|
||||
*should = true;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "soh/ResourceManagerHelpers.h"
|
||||
#include <libultraship/bridge/consolevariablebridge.h>
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "z64save.h"
|
||||
#include "objects/object_gi_compass/object_gi_compass.h"
|
||||
#include "objects/object_gi_map/object_gi_map.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/randomizer/SeedContext.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "soh/Enhancements/randomizer/SeedContext.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "soh/Enhancements/randomizer/entrance.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer_entrance_tracker.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
#include <soh/OTRGlobals.h>
|
||||
|
||||
extern "C" {
|
||||
#include <variables.h>
|
||||
@@ -12,12 +12,12 @@ extern PlayState* gPlayState;
|
||||
// clang-format attempts to format this strangely for some reason, so temporarily turning it off
|
||||
#define ENTRANCES_SHUFFLED \
|
||||
IS_RANDO && \
|
||||
OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_ENTRANCES).Is(RO_GENERIC_ON) && \
|
||||
Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_ENTRANCES).Is(RO_GENERIC_ON) && \
|
||||
(CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("EntrancesOnSigns"), 0) == 1)
|
||||
// clang-format on
|
||||
|
||||
void BuildEntranceHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
||||
auto ctx = OTRGlobals::Instance->gRandoContext;
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
s16 entrance = -1;
|
||||
switch (*textId) {
|
||||
case TEXT_WATERFALL:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Handles the randomized silly messages that the Fire Temple
|
||||
* trapped Gorons have when you free them.
|
||||
*/
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* and Carpet Salesman)
|
||||
*/
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* text changes that don't really fit anywhere else.
|
||||
*/
|
||||
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This file is responsible for the messages
|
||||
* for the Rando-Relevant Navi Hints enhancement.
|
||||
*/
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* This file is for handling the Randomize Rupee Names enhancement
|
||||
*/
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -38,7 +38,6 @@ Context::Context() {
|
||||
mDungeons = std::make_shared<Dungeons>();
|
||||
mLogic = std::make_shared<Logic>();
|
||||
mTrials = std::make_shared<Trials>();
|
||||
mFishsanity = std::make_shared<Fishsanity>();
|
||||
}
|
||||
|
||||
RandomizerArea Context::GetAreaFromString(std::string str) {
|
||||
@@ -185,7 +184,7 @@ void Context::GenerateLocationPool() {
|
||||
(location.GetRCType() == RCTYPE_COW && mOptions[RSK_SHUFFLE_COWS].Is(RO_GENERIC_OFF)) ||
|
||||
(location.GetRandomizerCheck() == RC_LH_HYRULE_LOACH &&
|
||||
mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_HYRULE_LOACH)) ||
|
||||
(location.GetRCType() == RCTYPE_FISH && !mFishsanity->GetFishLocationIncluded(&location)) ||
|
||||
(location.GetRCType() == RCTYPE_FISH && !Fishsanity::GetFishLocationIncluded(&location)) ||
|
||||
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OFF)) ||
|
||||
(location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_OFF)) ||
|
||||
(location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF)) ||
|
||||
@@ -496,10 +495,6 @@ std::shared_ptr<Dungeons> Context::GetDungeons() {
|
||||
return mDungeons;
|
||||
}
|
||||
|
||||
std::shared_ptr<Fishsanity> Context::GetFishsanity() {
|
||||
return mFishsanity;
|
||||
}
|
||||
|
||||
DungeonInfo* Context::GetDungeon(size_t key) const {
|
||||
return mDungeons->GetDungeon(static_cast<DungeonKey>(key));
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "randomizerTypes.h"
|
||||
#include "item_override.h"
|
||||
#include "hint.h"
|
||||
#include "fishsanity.h"
|
||||
#include "trial.h"
|
||||
|
||||
#include <memory>
|
||||
@@ -86,7 +85,6 @@ class Context {
|
||||
const std::set<RandomizerTrick>& enabledTricks);
|
||||
std::shared_ptr<EntranceShuffler> GetEntranceShuffler();
|
||||
std::shared_ptr<Dungeons> GetDungeons();
|
||||
std::shared_ptr<Fishsanity> GetFishsanity();
|
||||
DungeonInfo* GetDungeon(size_t key) const;
|
||||
DungeonInfo* GetDungeonFromScene(SceneID key) const;
|
||||
std::shared_ptr<Logic> GetLogic();
|
||||
@@ -195,7 +193,6 @@ class Context {
|
||||
std::shared_ptr<Dungeons> mDungeons;
|
||||
std::shared_ptr<Logic> mLogic;
|
||||
std::shared_ptr<Trials> mTrials;
|
||||
std::shared_ptr<Fishsanity> mFishsanity;
|
||||
std::shared_ptr<Kaleido> mKaleido;
|
||||
bool mSeedGenerated = false;
|
||||
bool mSpoilerLoaded = false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "static_data.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
#include "soh/Enhancements/randomizer/RCToRandInf.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "static_data.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
#include "soh/Enhancements/randomizer/RCToRandInf.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh_assets.h"
|
||||
#include "static_data.h"
|
||||
#include <libultraship/libultra.h>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "randomizer_grotto.h"
|
||||
#include "draw.h"
|
||||
#include "static_data.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh_assets.h"
|
||||
#include "static_data.h"
|
||||
#include "item_category_adj.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "item_category_adj.h"
|
||||
#include "particle_cmc.h"
|
||||
#include "soh/frame_interpolation.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh_assets.h"
|
||||
#include "static_data.h"
|
||||
#include "item_category_adj.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
#include "item_category_adj.h"
|
||||
#include "particle_cmc.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "ShuffleRocks.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "static_data.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
#include "item_category_adj.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
#include "item_category_adj.h"
|
||||
#include "particle_cmc.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "dungeon.h"
|
||||
#include "SeedContext.h"
|
||||
#include "draw.h"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/SeedContext.h"
|
||||
extern "C" {
|
||||
#include "z64.h"
|
||||
#include "functions.h"
|
||||
#include "soh/Enhancements/randomizer/SeedContext.h"
|
||||
#include "overlays/actors/ovl_En_Ossan/z_en_ossan.h"
|
||||
extern "C" {
|
||||
extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh_assets.h"
|
||||
#include "static_data.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include <soh/GameVersions.h>
|
||||
#include "soh/ResourceManagerHelpers.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Traps.h"
|
||||
#include <libultraship/bridge/consolevariablebridge.h>
|
||||
#include "soh/Enhancements/randomizer/SeedContext.h"
|
||||
#include "soh/Enhancements/randomizer/static_data.h"
|
||||
#include "soh/ShipUtils.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "entrance.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
|
||||
#include "3drando/fill.hpp"
|
||||
#include "3drando/pool_functions.hpp"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "3drando/pool_functions.hpp"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "../../OTRGlobals.h"
|
||||
#include "fishsanity.h"
|
||||
#include "draw.h"
|
||||
#include "soh/frame_interpolation.h"
|
||||
#include "variables.h"
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
@@ -50,160 +51,35 @@ std::unordered_map<int8_t, RandomizerCheck> Rando::StaticData::randomizerGrottoF
|
||||
{ 0x29, RC_ZR_OPEN_GROTTO_FISH }
|
||||
};
|
||||
|
||||
ActorFunc drawFishing = NULL;
|
||||
ActorFunc drawEnFish = NULL;
|
||||
Color_RGB8 fsPulseColor = { 30, 240, 200 };
|
||||
typedef struct {
|
||||
u8 mode;
|
||||
u8 numFish;
|
||||
bool ageSplit;
|
||||
} FishsanityPondOptions;
|
||||
|
||||
typedef enum {
|
||||
FSC_NONE,
|
||||
FSC_POND,
|
||||
FSC_GROTTO,
|
||||
FSC_ZD,
|
||||
} FishsanityCheckType;
|
||||
|
||||
static const CheckIdentity defaultIdentity = { RAND_INF_MAX, RC_UNKNOWN_CHECK };
|
||||
|
||||
static CheckIdentity NextChildPondFish = defaultIdentity;
|
||||
static CheckIdentity NextAdultPondFish = defaultIdentity;
|
||||
|
||||
static ActorFunc drawFishing = NULL;
|
||||
static ActorFunc drawEnFish = NULL;
|
||||
static Color_RGB8 fsPulseColor = { 30, 240, 200 };
|
||||
|
||||
static s16 fishGroupCounter = 0;
|
||||
static bool enableAdvance = false;
|
||||
|
||||
static CheckIdentity IdentifyFish(s32 sceneNum, s32 actorParams) {
|
||||
CheckIdentity fishIdentity;
|
||||
|
||||
fishIdentity.randomizerInf = RAND_INF_MAX;
|
||||
fishIdentity.randomizerCheck = RC_UNKNOWN_CHECK;
|
||||
|
||||
// Fishsanity will determine what the identity of the fish should be
|
||||
if (sceneNum == SCENE_FISHING_POND) {
|
||||
return OTRGlobals::Instance->gRandoContext->GetFishsanity()->IdentifyPondFish(actorParams);
|
||||
}
|
||||
|
||||
Rando::Location* location =
|
||||
OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(ACTOR_EN_FISH, sceneNum, actorParams);
|
||||
|
||||
if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) {
|
||||
fishIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()];
|
||||
fishIdentity.randomizerCheck = location->GetRandomizerCheck();
|
||||
}
|
||||
|
||||
return fishIdentity;
|
||||
}
|
||||
|
||||
namespace Rando {
|
||||
const CheckIdentity Fishsanity::defaultIdentity = { RAND_INF_MAX, RC_UNKNOWN_CHECK };
|
||||
bool Fishsanity::fishsanityHelpersInit = false;
|
||||
std::unordered_map<RandomizerCheck, LinkAge> Fishsanity::pondFishAgeMap;
|
||||
std::vector<RandomizerCheck> Fishsanity::childPondFish;
|
||||
std::vector<RandomizerCheck> Fishsanity::adultPondFish;
|
||||
|
||||
Fishsanity::Fishsanity() {
|
||||
InitializeHelpers();
|
||||
}
|
||||
|
||||
Fishsanity::~Fishsanity() {
|
||||
}
|
||||
|
||||
bool Fishsanity::GetFishLocationIncluded(Rando::Location* loc, FishsanityOptionsSource optionsSource) {
|
||||
auto [mode, numFish, ageSplit] = GetOptions(optionsSource);
|
||||
|
||||
if (loc->GetRCType() != RCTYPE_FISH || mode == RO_FISHSANITY_OFF || mode == RO_FISHSANITY_HYRULE_LOACH) {
|
||||
return false;
|
||||
}
|
||||
RandomizerCheck rc = loc->GetRandomizerCheck();
|
||||
// Are pond fish enabled, and is this a pond fish location?
|
||||
if (mode != RO_FISHSANITY_OVERWORLD && numFish > 0 && loc->GetScene() == SCENE_FISHING_POND &&
|
||||
loc->GetActorID() == ACTOR_FISHING) {
|
||||
// Is this a child fish location? If so, is it within the defined number of pond fish checks?
|
||||
if (rc >= RC_LH_CHILD_FISH_1 && rc <= RC_LH_CHILD_LOACH_2 && numFish > (loc->GetActorParams() - 100)) {
|
||||
return true;
|
||||
}
|
||||
// Are adult fish available, and is this an adult fish location? If so, is it within the defined number of pond
|
||||
// fish checks?
|
||||
if (ageSplit && rc >= RC_LH_ADULT_FISH_1 && rc <= RC_LH_ADULT_LOACH &&
|
||||
numFish > (loc->GetActorParams() - 100)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 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) &&
|
||||
loc->GetActorID() == ACTOR_EN_FISH && (loc->GetActorParams() >> 8)) {
|
||||
return true;
|
||||
}
|
||||
// Must not be an included fish location!
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<std::vector<RandomizerCheck>, std::vector<RandomizerCheck>>
|
||||
Fishsanity::GetFishingPondLocations(FishsanityOptionsSource optionsSource) {
|
||||
auto [mode, numFish, ageSplit] = GetOptions(optionsSource);
|
||||
std::vector<RandomizerCheck> activeFish;
|
||||
std::vector<RandomizerCheck> remainingFish;
|
||||
std::vector<RandomizerCheck> pondFish = Rando::StaticData::GetPondFishLocations();
|
||||
|
||||
// Fishsanity_InitializeHelpers();
|
||||
remainingFish.insert(remainingFish.end(), pondFish.begin(), pondFish.end());
|
||||
|
||||
// No pond fish shuffled
|
||||
if (numFish == 0) {
|
||||
return std::make_pair(activeFish, remainingFish);
|
||||
}
|
||||
// Every pond fish is shuffled, so we can save some time
|
||||
if (numFish > 16) {
|
||||
// Child and adult pond fish are both shuffled, set activeFish to remainingFish and return an empty vector for
|
||||
// inactive fish.
|
||||
if (ageSplit) {
|
||||
return std::make_pair(remainingFish, activeFish);
|
||||
}
|
||||
// Activate all child fish only
|
||||
activeFish = FilterAndEraseFromPool(
|
||||
remainingFish, [](const RandomizerCheck loc) { return pondFishAgeMap[loc] == LINK_AGE_CHILD; });
|
||||
return std::make_pair(activeFish, remainingFish);
|
||||
}
|
||||
// Only some pond fish are shuffled, so we have to only activate the requested number.
|
||||
activeFish.insert(activeFish.end(), childPondFish.begin(), childPondFish.begin() + numFish);
|
||||
// If pond is split, also add the requested number of adult fish.
|
||||
if (ageSplit) {
|
||||
activeFish.insert(activeFish.end(), adultPondFish.begin(),
|
||||
adultPondFish.begin() + std::min<uint8_t>(numFish, 16));
|
||||
}
|
||||
// NOTE: This only works because we can assume activeFish is already sorted; changes that break this assumption will
|
||||
// also break this
|
||||
std::erase_if(remainingFish,
|
||||
[&](RandomizerCheck loc) { return std::binary_search(activeFish.begin(), activeFish.end(), loc); });
|
||||
|
||||
return std::make_pair(activeFish, remainingFish);
|
||||
}
|
||||
|
||||
std::pair<std::vector<RandomizerCheck>, std::vector<RandomizerCheck>>
|
||||
Fishsanity::GetFishsanityLocations(FishsanityOptionsSource optionsSource) {
|
||||
auto [mode, numFish, ageSplit] = GetOptions(optionsSource);
|
||||
std::vector<RandomizerCheck> activeFish;
|
||||
std::vector<RandomizerCheck> remainingFish;
|
||||
|
||||
// Add pond fish
|
||||
if (mode == RO_FISHSANITY_POND || mode == RO_FISHSANITY_BOTH) {
|
||||
auto pondLocations = GetFishingPondLocations(optionsSource);
|
||||
activeFish.insert(activeFish.end(), pondLocations.first.begin(), pondLocations.first.end());
|
||||
remainingFish.insert(remainingFish.end(), pondLocations.second.begin(), pondLocations.second.end());
|
||||
}
|
||||
|
||||
// Add overworld fish
|
||||
if (mode == RO_FISHSANITY_OVERWORLD || mode == RO_FISHSANITY_BOTH) {
|
||||
std::vector<RandomizerCheck> overworldFish = Rando::StaticData::GetOverworldFishLocations();
|
||||
activeFish.insert(activeFish.end(), overworldFish.begin(), overworldFish.end());
|
||||
}
|
||||
|
||||
return std::make_pair(activeFish, remainingFish);
|
||||
}
|
||||
|
||||
CheckIdentity Fishsanity::IdentifyPondFish(u8 fishParams) {
|
||||
auto [mode, pondCount, ageSplit] = GetOptions();
|
||||
CheckIdentity identity = defaultIdentity;
|
||||
|
||||
if (!GetPondFishShuffled()) {
|
||||
return identity;
|
||||
}
|
||||
|
||||
if (pondCount > 16) {
|
||||
identity = GetPondFish(fishParams, IsAdultPond());
|
||||
} else {
|
||||
identity = LINK_IS_ADULT ? mCurrPondFish.second : mCurrPondFish.first;
|
||||
}
|
||||
|
||||
return identity;
|
||||
}
|
||||
|
||||
FishsanityPondOptions Fishsanity::GetOptions(FishsanityOptionsSource optionsSource) {
|
||||
/**
|
||||
* @brief Get fishsanity fishing pond options from the requested source
|
||||
*/
|
||||
static FishsanityPondOptions GetOptions(FishsanityOptionsSource optionsSource = FSO_SOURCE_RANDO) {
|
||||
FishsanityPondOptions options{};
|
||||
switch (optionsSource) {
|
||||
// Used in check tracker
|
||||
@@ -222,13 +98,101 @@ FishsanityPondOptions Fishsanity::GetOptions(FishsanityOptionsSource optionsSour
|
||||
return options;
|
||||
}
|
||||
|
||||
void Fishsanity::UpdateCurrentPondFish() {
|
||||
auto [mode, pondCount, ageSplit] = GetOptions();
|
||||
mCurrPondFish = std::pair<CheckIdentity, CheckIdentity>();
|
||||
mCurrPondFish.first = defaultIdentity;
|
||||
mCurrPondFish.second = defaultIdentity;
|
||||
/**
|
||||
* @brief Returns true if the fishing pond is shuffled
|
||||
*/
|
||||
static bool GetPondFishShuffled() {
|
||||
u8 fsMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
|
||||
return OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_POND_COUNT) > 0 &&
|
||||
(fsMode == RO_FISHSANITY_POND || fsMode == RO_FISHSANITY_BOTH);
|
||||
}
|
||||
|
||||
// Initialize mCurrPondFish if we're shuffling pond fish, but if all fish are shuffled, we don't need to use this.
|
||||
/**
|
||||
* @brief Returns true if overworld fish are shuffled
|
||||
*/
|
||||
static bool GetOverworldFishShuffled() {
|
||||
u8 fsMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
|
||||
return fsMode == RO_FISHSANITY_OVERWORLD || fsMode == RO_FISHSANITY_BOTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the fishing pond is currently adult (i.e., age split is enabled and Link is adult)
|
||||
*/
|
||||
static bool IsAdultPond() {
|
||||
return LINK_IS_ADULT && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_AGE_SPLIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the type of a fishsanity check
|
||||
*/
|
||||
static FishsanityCheckType GetCheckType(RandomizerCheck rc) {
|
||||
// if it's not RCTYPE_FISH, obviously it's not a fish
|
||||
if (Rando::StaticData::GetLocation(rc)->GetRCType() != RCTYPE_FISH) {
|
||||
return FSC_NONE;
|
||||
}
|
||||
|
||||
auto loc = Rando::StaticData::GetLocation(rc);
|
||||
switch (loc->GetScene()) {
|
||||
case SCENE_FISHING_POND:
|
||||
return FSC_POND;
|
||||
case SCENE_ZORAS_DOMAIN:
|
||||
return FSC_ZD;
|
||||
case SCENE_GROTTOS:
|
||||
return FSC_GROTTO;
|
||||
default:
|
||||
return FSC_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the given CheckIdentity represents an actual fish
|
||||
*/
|
||||
static bool IsFish(CheckIdentity* fish) {
|
||||
if (fish->randomizerCheck == RC_UNKNOWN_CHECK || fish->randomizerInf == RAND_INF_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetCheckType(fish->randomizerCheck) != FSC_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resolves a pond fish's CheckIdentity directly from params & pond age
|
||||
*/
|
||||
static CheckIdentity GetPondFish(s16 params, bool adultPond) {
|
||||
auto pair = Rando::StaticData::randomizerFishingPondFish[params - 100];
|
||||
RandomizerCheck rc = adultPond ? pair.second : pair.first;
|
||||
return { OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc), rc };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the identity for a caught pond fish given its params
|
||||
*/
|
||||
static CheckIdentity IdentifyPondFish(u8 fishParams) {
|
||||
auto [mode, pondCount, ageSplit] = GetOptions();
|
||||
CheckIdentity identity = defaultIdentity;
|
||||
|
||||
if (!GetPondFishShuffled()) {
|
||||
return identity;
|
||||
}
|
||||
|
||||
if (pondCount > 16) {
|
||||
identity = GetPondFish(fishParams, IsAdultPond());
|
||||
} else {
|
||||
identity = LINK_IS_ADULT ? NextAdultPondFish : NextChildPondFish;
|
||||
}
|
||||
|
||||
return identity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates current pond fish according to save data
|
||||
*/
|
||||
static void UpdateCurrentPondFish() {
|
||||
auto [mode, pondCount, ageSplit] = GetOptions();
|
||||
NextChildPondFish = defaultIdentity;
|
||||
NextAdultPondFish = defaultIdentity;
|
||||
|
||||
// Initialize next pond fish if we're shuffling pond fish, but if all fish are shuffled, we don't need to use this.
|
||||
if ((mode == RO_FISHSANITY_BOTH || mode == RO_FISHSANITY_POND) && pondCount < 17) {
|
||||
// find the first inf that isn't set yet for each age
|
||||
// but don't go past the max number
|
||||
@@ -239,47 +203,31 @@ void Fishsanity::UpdateCurrentPondFish() {
|
||||
OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(tableEntry.first)) ||
|
||||
i == pondCount - 1) {
|
||||
// Found first child check
|
||||
if (!IsFish(&mCurrPondFish.first)) {
|
||||
mCurrPondFish.first = GetPondFish(params, false);
|
||||
if (!IsFish(&NextChildPondFish)) {
|
||||
NextChildPondFish = GetPondFish(params, false);
|
||||
}
|
||||
|
||||
if (!ageSplit && !IsFish(&mCurrPondFish.second)) {
|
||||
mCurrPondFish.second = GetPondFish(params, false);
|
||||
if (!ageSplit && !IsFish(&NextAdultPondFish)) {
|
||||
NextAdultPondFish = GetPondFish(params, false);
|
||||
// both ages are resolved! we can quit here
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ageSplit && !IsFish(&mCurrPondFish.second) && tableEntry.second != RC_UNKNOWN_CHECK &&
|
||||
if (ageSplit && !IsFish(&NextAdultPondFish) && tableEntry.second != RC_UNKNOWN_CHECK &&
|
||||
(!Flags_GetRandomizerInf(
|
||||
OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(tableEntry.second)) ||
|
||||
i == pondCount - 1)) {
|
||||
mCurrPondFish.second = GetPondFish(params, true);
|
||||
NextAdultPondFish = GetPondFish(params, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Fishsanity::InitializeFromSave() {
|
||||
UpdateCurrentPondFish();
|
||||
}
|
||||
|
||||
bool Fishsanity::GetPondFishShuffled() {
|
||||
u8 fsMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
|
||||
return OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_POND_COUNT) > 0 &&
|
||||
(fsMode == RO_FISHSANITY_POND || fsMode == RO_FISHSANITY_BOTH);
|
||||
}
|
||||
|
||||
bool Fishsanity::GetOverworldFishShuffled() {
|
||||
u8 fsMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
|
||||
return fsMode == RO_FISHSANITY_OVERWORLD || fsMode == RO_FISHSANITY_BOTH;
|
||||
}
|
||||
|
||||
bool Fishsanity::IsAdultPond() {
|
||||
return LINK_IS_ADULT && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_AGE_SPLIT);
|
||||
}
|
||||
|
||||
bool Fishsanity::GetPondCleared() {
|
||||
/**
|
||||
* @brief Returns true if all available pond fish checks have been collected for the current age
|
||||
*/
|
||||
static bool GetPondCleared() {
|
||||
auto [mode, pondCount, ageSplit] = GetOptions();
|
||||
// no fish shuffled, so pond is always cleared :thumbsup:
|
||||
if (pondCount == 0) {
|
||||
@@ -307,187 +255,45 @@ bool Fishsanity::GetPondCleared() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Fishsanity::GetDomainCleared() {
|
||||
for (RandomizerInf i = RAND_INF_ZD_FISH_1; i <= RAND_INF_ZD_FISH_5; i = (RandomizerInf)(i + 1)) {
|
||||
if (!Flags_GetRandomizerInf(i)) {
|
||||
return false;
|
||||
}
|
||||
static CheckIdentity IdentifyFish(s32 sceneNum, s32 actorParams) {
|
||||
CheckIdentity fishIdentity;
|
||||
|
||||
fishIdentity.randomizerInf = RAND_INF_MAX;
|
||||
fishIdentity.randomizerCheck = RC_UNKNOWN_CHECK;
|
||||
|
||||
// Fishsanity will determine what the identity of the fish should be
|
||||
if (sceneNum == SCENE_FISHING_POND) {
|
||||
return IdentifyPondFish(actorParams);
|
||||
}
|
||||
return true;
|
||||
|
||||
Rando::Location* location =
|
||||
OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(ACTOR_EN_FISH, sceneNum, actorParams);
|
||||
|
||||
if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) {
|
||||
fishIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()];
|
||||
fishIdentity.randomizerCheck = location->GetRandomizerCheck();
|
||||
}
|
||||
|
||||
return fishIdentity;
|
||||
}
|
||||
|
||||
void Fishsanity::InitializeHelpers() {
|
||||
if (fishsanityHelpersInit) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto pair : Rando::StaticData::randomizerFishingPondFish) {
|
||||
pondFishAgeMap[pair.first] = LINK_AGE_CHILD;
|
||||
pondFishAgeMap[pair.second] = LINK_AGE_ADULT;
|
||||
childPondFish.push_back(pair.first);
|
||||
adultPondFish.push_back(pair.second);
|
||||
}
|
||||
static void Fishsanity_OpenGreyscaleColor(PlayState* play, Color_RGB8* color, int16_t frameOffset) {
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
gDPSetGrayscaleColor(POLY_OPA_DISP++, color->r, color->g, color->b,
|
||||
// Make color pulse, offset a bit by the actor params
|
||||
ABS(255.0f * Math_CosS((play->gameplayFrames + frameOffset) * 1000)));
|
||||
gSPGrayscale(POLY_OPA_DISP++, true);
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
|
||||
CheckIdentity Fishsanity::GetPondFish(s16 params, bool adultPond) {
|
||||
auto pair = Rando::StaticData::randomizerFishingPondFish[params - 100];
|
||||
RandomizerCheck rc = adultPond ? pair.second : pair.first;
|
||||
return { OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc), rc };
|
||||
static void Fishsanity_CloseGreyscaleColor(PlayState* play) {
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
gSPGrayscale(POLY_OPA_DISP++, false);
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
|
||||
CheckIdentity Fishsanity::AdvancePond() {
|
||||
auto [mode, pondCount, ageSplit] = GetOptions();
|
||||
|
||||
// No need to update state with full pond shuffle
|
||||
if (pondCount > 16) {
|
||||
return defaultIdentity;
|
||||
}
|
||||
|
||||
UpdateCurrentPondFish();
|
||||
|
||||
return IsAdultPond() ? mCurrPondFish.second : mCurrPondFish.first;
|
||||
}
|
||||
|
||||
FishsanityCheckType Fishsanity::GetCheckType(RandomizerCheck rc) {
|
||||
// if it's not RCTYPE_FISH, obviously it's not a fish
|
||||
if (Rando::StaticData::GetLocation(rc)->GetRCType() != RCTYPE_FISH) {
|
||||
return FSC_NONE;
|
||||
}
|
||||
|
||||
auto loc = Rando::StaticData::GetLocation(rc);
|
||||
switch (loc->GetScene()) {
|
||||
case SCENE_FISHING_POND:
|
||||
return FSC_POND;
|
||||
case SCENE_ZORAS_DOMAIN:
|
||||
return FSC_ZD;
|
||||
case SCENE_GROTTOS:
|
||||
return FSC_GROTTO;
|
||||
default:
|
||||
return FSC_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
bool Fishsanity::IsFish(CheckIdentity* fish) {
|
||||
if (fish->randomizerCheck == RC_UNKNOWN_CHECK || fish->randomizerInf == RAND_INF_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetCheckType(fish->randomizerCheck) != FSC_NONE;
|
||||
}
|
||||
|
||||
void Fishsanity::OnActorInitHandler(void* refActor) {
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
|
||||
auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
|
||||
CheckIdentity 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 = 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 = 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).Get() > 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
CheckIdentity identity = IdentifyFish(gPlayState->sceneNum, actor->params);
|
||||
if (identity.randomizerCheck != RC_UNKNOWN_CHECK) {
|
||||
Flags_SetRandomizerInf(identity.randomizerInf);
|
||||
enableAdvance = true;
|
||||
// Remove uncaught effect
|
||||
if (actor->shape.shadowDraw != NULL) {
|
||||
actor->shape.shadowDraw = NULL;
|
||||
actor->draw = drawFishing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (actor->id == ACTOR_EN_FISH && fs->GetOverworldFishShuffled()) {
|
||||
CheckIdentity fish = 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_CULLING_DISABLED) && fs->GetOverworldFishShuffled()) {
|
||||
fishGroupCounter = 0;
|
||||
}
|
||||
}
|
||||
} // namespace Rando
|
||||
|
||||
// C interface
|
||||
extern "C" {
|
||||
bool Randomizer_GetPondFishShuffled() {
|
||||
return Rando::Context::GetInstance()->GetFishsanity()->GetPondFishShuffled();
|
||||
}
|
||||
|
||||
bool Randomizer_GetOverworldFishShuffled() {
|
||||
return Rando::Context::GetInstance()->GetFishsanity()->GetOverworldFishShuffled();
|
||||
}
|
||||
|
||||
bool Randomizer_IsAdultPond() {
|
||||
return Rando::Context::GetInstance()->GetFishsanity()->IsAdultPond();
|
||||
}
|
||||
|
||||
void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play) {
|
||||
/// Custom shadow draw function to add effect to uncollected fish
|
||||
static void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play) {
|
||||
Vec3f pos, ripplePos;
|
||||
static Vec3f velocity = { 0.0f, 0.0f, 0.0f };
|
||||
static Vec3f accel = { 0.0f, 0.0f, 0.0f };
|
||||
@@ -527,7 +333,8 @@ void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play) {
|
||||
}
|
||||
}
|
||||
|
||||
void Fishsanity_DrawEnFish(struct Actor* actor, struct PlayState* play) {
|
||||
/// Overridden actor draw function for bottleable fish
|
||||
static void Fishsanity_DrawEnFish(Actor* actor, PlayState* play) {
|
||||
CheckIdentity fish = IdentifyFish(play->sceneNum, actor->params);
|
||||
GetItemEntry randoItem = Rando::Context::GetInstance()->GetFinalGIEntry(fish.randomizerCheck, true, GI_FISH);
|
||||
if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) {
|
||||
@@ -545,28 +352,149 @@ void Fishsanity_DrawEnFish(struct Actor* actor, struct PlayState* play) {
|
||||
Matrix_Pop();
|
||||
}
|
||||
|
||||
void Fishsanity_DrawFishing(struct Actor* actor, struct PlayState* play) {
|
||||
/// Overridden actor draw function for the fishing pond
|
||||
static void Fishsanity_DrawFishing(Actor* actor, PlayState* play) {
|
||||
Fishsanity_OpenGreyscaleColor(play, &fsPulseColor, (actor->params - 100) * 20);
|
||||
drawFishing(actor, play);
|
||||
Fishsanity_CloseGreyscaleColor(play);
|
||||
}
|
||||
|
||||
void Fishsanity_OpenGreyscaleColor(PlayState* play, Color_RGB8* color, int16_t frameOffset) {
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
gDPSetGrayscaleColor(POLY_OPA_DISP++, color->r, color->g, color->b,
|
||||
// Make color pulse, offset a bit by the actor params
|
||||
ABS(255.0f * Math_CosS((play->gameplayFrames + frameOffset) * 1000)));
|
||||
gSPGrayscale(POLY_OPA_DISP++, true);
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
/**
|
||||
* @brief ActorInit hook handler for fishsanity
|
||||
*/
|
||||
static void OnActorInitHandler(void* refActor) {
|
||||
Actor* actor = static_cast<Actor*>(refActor);
|
||||
|
||||
CheckIdentity fish;
|
||||
|
||||
if (actor->id == ACTOR_EN_FISH && 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 = IdentifyFish(gPlayState->sceneNum, actor->params);
|
||||
// Render fish as randomized item
|
||||
if (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 && GetPondFishShuffled()) {
|
||||
// Initialize pond fish for fishsanity
|
||||
fish = 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).Get() > 16 && !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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Fishsanity_CloseGreyscaleColor(PlayState* play) {
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
gSPGrayscale(POLY_OPA_DISP++, false);
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
/**
|
||||
* @brief ActorUpdate hook handler for fishsanity
|
||||
*/
|
||||
static void 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);
|
||||
|
||||
// Detect fish catch
|
||||
if (actor->id == ACTOR_FISHING && GetPondFishShuffled()) {
|
||||
Fishing* fish = static_cast<Fishing*>(refActor);
|
||||
|
||||
// State 6 -> Fish caught and hoisted
|
||||
if (fish->fishState == 6) {
|
||||
CheckIdentity identity = IdentifyFish(gPlayState->sceneNum, actor->params);
|
||||
if (identity.randomizerCheck != RC_UNKNOWN_CHECK) {
|
||||
Flags_SetRandomizerInf(identity.randomizerInf);
|
||||
enableAdvance = true;
|
||||
// Remove uncaught effect
|
||||
if (actor->shape.shadowDraw != NULL) {
|
||||
actor->shape.shadowDraw = NULL;
|
||||
actor->draw = drawFishing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (actor->id == ACTOR_EN_FISH && GetOverworldFishShuffled()) {
|
||||
CheckIdentity fish = IdentifyFish(gPlayState->sceneNum, actor->params);
|
||||
EnFish* fishActor = static_cast<EnFish*>(refActor);
|
||||
if (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_CULLING_DISABLED) && GetOverworldFishShuffled()) {
|
||||
fishGroupCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Rando::Fishsanity {
|
||||
|
||||
bool GetFishLocationIncluded(Rando::Location* loc, FishsanityOptionsSource optionsSource) {
|
||||
auto [mode, numFish, ageSplit] = GetOptions(optionsSource);
|
||||
|
||||
if (loc->GetRCType() != RCTYPE_FISH || mode == RO_FISHSANITY_OFF || mode == RO_FISHSANITY_HYRULE_LOACH) {
|
||||
return false;
|
||||
}
|
||||
RandomizerCheck rc = loc->GetRandomizerCheck();
|
||||
// Are pond fish enabled, and is this a pond fish location?
|
||||
if (mode != RO_FISHSANITY_OVERWORLD && numFish > 0 && loc->GetScene() == SCENE_FISHING_POND &&
|
||||
loc->GetActorID() == ACTOR_FISHING) {
|
||||
// Is this a child fish location? If so, is it within the defined number of pond fish checks?
|
||||
if (rc >= RC_LH_CHILD_FISH_1 && rc <= RC_LH_CHILD_LOACH_2 && numFish > (loc->GetActorParams() - 100)) {
|
||||
return true;
|
||||
}
|
||||
// Are adult fish available, and is this an adult fish location? If so, is it within the defined number of pond
|
||||
// fish checks?
|
||||
if (ageSplit && rc >= RC_LH_ADULT_FISH_1 && rc <= RC_LH_ADULT_LOACH &&
|
||||
numFish > (loc->GetActorParams() - 100)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// 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) &&
|
||||
loc->GetActorID() == ACTOR_EN_FISH && (loc->GetActorParams() >> 8)) {
|
||||
return true;
|
||||
}
|
||||
// Must not be an included fish location!
|
||||
return false;
|
||||
}
|
||||
|
||||
void InitializeFromSave() {
|
||||
UpdateCurrentPondFish();
|
||||
}
|
||||
|
||||
} // namespace Rando::Fishsanity
|
||||
|
||||
void RegisterShuffleFish() {
|
||||
bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_FISHSANITY).IsNot(RO_FISHSANITY_OFF);
|
||||
COND_HOOK(OnSceneInit, shouldRegister, [](int16_t sceneNum) {
|
||||
@@ -575,19 +503,18 @@ void RegisterShuffleFish() {
|
||||
}
|
||||
});
|
||||
|
||||
COND_HOOK(OnActorInit, shouldRegister, Rando::Fishsanity::OnActorInitHandler);
|
||||
COND_HOOK(OnActorUpdate, shouldRegister, Rando::Fishsanity::OnActorUpdateHandler);
|
||||
COND_HOOK(OnActorInit, shouldRegister, OnActorInitHandler);
|
||||
COND_HOOK(OnActorUpdate, shouldRegister, OnActorUpdateHandler);
|
||||
COND_HOOK(OnItemReceive, shouldRegister, [](GetItemEntry itemEntry) {
|
||||
if (enableAdvance) {
|
||||
enableAdvance = false;
|
||||
OTRGlobals::Instance->gRandoContext->GetFishsanity()->AdvancePond();
|
||||
UpdateCurrentPondFish();
|
||||
}
|
||||
});
|
||||
|
||||
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()) {
|
||||
if (actor->id == ACTOR_EN_FISH && GetOverworldFishShuffled()) {
|
||||
auto fish = IdentifyFish(gPlayState->sceneNum, actor->params);
|
||||
if (fish.randomizerCheck != RC_UNKNOWN_CHECK && !Flags_GetRandomizerInf(fish.randomizerInf)) {
|
||||
Flags_SetRandomizerInf(fish.randomizerInf);
|
||||
|
||||
@@ -1,209 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <z64.h>
|
||||
#include "randomizerTypes.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
|
||||
typedef struct {
|
||||
u8 mode;
|
||||
u8 numFish;
|
||||
bool ageSplit;
|
||||
} FishsanityPondOptions;
|
||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||
#include "soh/Enhancements/randomizer/location.h"
|
||||
|
||||
typedef enum {
|
||||
FSO_SOURCE_RANDO,
|
||||
FSO_SOURCE_CVARS,
|
||||
} FishsanityOptionsSource;
|
||||
|
||||
typedef enum {
|
||||
FSC_NONE,
|
||||
FSC_POND,
|
||||
FSC_GROTTO,
|
||||
FSC_ZD,
|
||||
} FishsanityCheckType;
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "soh/Enhancements/randomizer/location.h"
|
||||
|
||||
namespace Rando {
|
||||
namespace Rando::Fishsanity {
|
||||
|
||||
/**
|
||||
* @brief Class to provide an interface for and direct Fishsanity features
|
||||
* @brief Returns true if the given fish location is active
|
||||
*
|
||||
* @param loc The Location to check
|
||||
* @param optionsSource Optionally declare from which source to pull settings
|
||||
*/
|
||||
class Fishsanity {
|
||||
public:
|
||||
Fishsanity();
|
||||
~Fishsanity();
|
||||
bool GetFishLocationIncluded(Rando::Location* loc, FishsanityOptionsSource optionsSource = FSO_SOURCE_RANDO);
|
||||
|
||||
static const CheckIdentity defaultIdentity;
|
||||
/**
|
||||
* @brief Initializes pond fish state from save
|
||||
*/
|
||||
void InitializeFromSave();
|
||||
|
||||
/**
|
||||
* @brief Gets the type of a fishsanity check
|
||||
* @param rc The RandomizerCheck to categorize
|
||||
* @return The check's fishsanity type, or FSC_NONE
|
||||
*/
|
||||
static FishsanityCheckType GetCheckType(RandomizerCheck rc);
|
||||
|
||||
/**
|
||||
* @brief Returns true if the given CheckIdentity represents an actual fish
|
||||
* @param fish The fish to check
|
||||
*/
|
||||
static bool IsFish(CheckIdentity* fish);
|
||||
|
||||
/**
|
||||
* @brief Returns true if the given fish location is active
|
||||
*
|
||||
* @param loc The Location to check
|
||||
* @param optionsSource Optionally declare from which source to pull settings
|
||||
*/
|
||||
bool GetFishLocationIncluded(Rando::Location* loc, FishsanityOptionsSource optionsSource = FSO_SOURCE_RANDO);
|
||||
|
||||
/**
|
||||
* @brief Get the active and inactive locations in the fishing pond.
|
||||
*
|
||||
* @param optionsSource Optionally declare from which source to pull settings
|
||||
* @return A pair of vectors, where the fist is all active pond fish checks, and the second is all inactive pond
|
||||
* fish checks.
|
||||
*/
|
||||
std::pair<std::vector<RandomizerCheck>, std::vector<RandomizerCheck>>
|
||||
GetFishingPondLocations(FishsanityOptionsSource optionsSource = FSO_SOURCE_RANDO);
|
||||
|
||||
/**
|
||||
* @brief Get all active fishsanity locations, and all inactive fishing pond locations.
|
||||
*
|
||||
* @param optionsSource Optionally declare from which source to pull settings
|
||||
* @return A pair of vectors, where the first is all active fishsanity checks, and the second is all inactive
|
||||
* fishsanity checks.
|
||||
*/
|
||||
std::pair<std::vector<RandomizerCheck>, std::vector<RandomizerCheck>>
|
||||
GetFishsanityLocations(FishsanityOptionsSource optionsSource = FSO_SOURCE_RANDO);
|
||||
|
||||
/**
|
||||
* @brief Returns the identity for a caught pond fish given its params.
|
||||
* Not for use externally from rando
|
||||
*
|
||||
* @param fishParams Actor parameters for the fish to identify
|
||||
*/
|
||||
CheckIdentity IdentifyPondFish(u8 fishParams);
|
||||
|
||||
/**
|
||||
* @brief Get fishsanity fishing pond options from the requested source
|
||||
*/
|
||||
FishsanityPondOptions GetOptions(FishsanityOptionsSource optionsSource = FSO_SOURCE_RANDO);
|
||||
|
||||
/**
|
||||
* @brief Updates current pond fish according to save data
|
||||
*/
|
||||
void UpdateCurrentPondFish();
|
||||
|
||||
/**
|
||||
* @brief Initializes internal state from save
|
||||
*/
|
||||
void InitializeFromSave();
|
||||
|
||||
/**
|
||||
* @brief Returns true if the fishing pond is shuffled
|
||||
*/
|
||||
bool GetPondFishShuffled();
|
||||
|
||||
/**
|
||||
* @brief Returns true if overworld fish are shuffled
|
||||
*/
|
||||
bool GetOverworldFishShuffled();
|
||||
|
||||
/**
|
||||
* @brief Returns true if the fishing pond is currently adult (i.e., age split is enabled and Link is adult)
|
||||
*/
|
||||
bool IsAdultPond();
|
||||
|
||||
/**
|
||||
* @brief Returns true if all available pond fish checks have been collected for the current age
|
||||
*/
|
||||
bool GetPondCleared();
|
||||
|
||||
/**
|
||||
* @brief Returns true if all available Zora's Domain fish checks have been collected
|
||||
*/
|
||||
bool GetDomainCleared();
|
||||
|
||||
/**
|
||||
* @brief Advances current fishing pond check; no effect if every fish is shuffled
|
||||
* @return The new CheckIdentity for the current pond, or default identity if every fish is shuffled
|
||||
*/
|
||||
CheckIdentity AdvancePond();
|
||||
|
||||
/**
|
||||
* @brief ActorInit hook handler for fishsanity
|
||||
*/
|
||||
static void OnActorInitHandler(void* refActor);
|
||||
|
||||
/**
|
||||
* @brief ActorUpdate hook handler for fishsanity
|
||||
*/
|
||||
static void OnActorUpdateHandler(void* refActor);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Initialize helper statics if they have not been initialized yet
|
||||
*/
|
||||
void InitializeHelpers();
|
||||
|
||||
/**
|
||||
* @brief Resolves a pond fish's CheckIdentity directly from params & pond age
|
||||
*
|
||||
* @param params Params for Fishing actor
|
||||
* @param adultPond Whether to resolve this fish as an adult check
|
||||
* @return The CheckIdentity for the described fish
|
||||
*/
|
||||
static CheckIdentity GetPondFish(s16 params, bool adultPond);
|
||||
|
||||
/**
|
||||
* @brief Current pond fish when all pond fish are not randomized
|
||||
*/
|
||||
std::pair<CheckIdentity, CheckIdentity> mCurrPondFish;
|
||||
|
||||
/**
|
||||
* @brief True if fishsanity helpers have been initialized
|
||||
*/
|
||||
static bool fishsanityHelpersInit;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//// Helper data structures derived from static data ////
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Mapping from pond fish check to the age where that check can be collected
|
||||
*/
|
||||
static std::unordered_map<RandomizerCheck, LinkAge> pondFishAgeMap;
|
||||
|
||||
/**
|
||||
* @brief List of child pond fish checks
|
||||
*/
|
||||
static std::vector<RandomizerCheck> childPondFish;
|
||||
|
||||
/**
|
||||
* @brief List of adult pond fish checks
|
||||
*/
|
||||
static std::vector<RandomizerCheck> adultPondFish;
|
||||
};
|
||||
} // namespace Rando
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
/// Returns true if pond fish should be shuffled based on fishsanity settings.
|
||||
bool Randomizer_GetPondFishShuffled();
|
||||
/// Returns true if overworld fish should be shuffled based on fishsanity settings.
|
||||
bool Randomizer_GetOverworldFishShuffled();
|
||||
/// Returns true if the adult fishing pond should be used for fishsanity.
|
||||
bool Randomizer_IsAdultPond();
|
||||
/// Custom shadow draw function to add effect to uncollected fish
|
||||
void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play);
|
||||
/// Overridden actor draw function for bottleable fish
|
||||
void Fishsanity_DrawEnFish(struct Actor* actor, struct PlayState* play);
|
||||
/// Overridden actor draw function for the fishing pond
|
||||
void Fishsanity_DrawFishing(struct Actor* actor, struct PlayState* play);
|
||||
void Fishsanity_OpenGreyscaleColor(PlayState* play, Color_RGB8* color, int16_t frameOffset);
|
||||
void Fishsanity_CloseGreyscaleColor(PlayState* play);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
} // namespace Rando::Fishsanity
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||
#include "soh/Enhancements/randomizer/bean_patches.h"
|
||||
#include "soh/Enhancements/randomizer/dungeon.h"
|
||||
#include "soh/Enhancements/randomizer/fishsanity.h"
|
||||
#include "soh/Enhancements/randomizer/static_data.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
@@ -2913,7 +2914,7 @@ static void RandomizerRegisterHooks() {
|
||||
RandomizerOnKaleidoscopeUpdateHandler);
|
||||
|
||||
if (RAND_GET_OPTION(RSK_FISHSANITY).IsNot(RO_FISHSANITY_OFF)) {
|
||||
OTRGlobals::Instance->gRandoContext->GetFishsanity()->InitializeFromSave();
|
||||
Rando::Fishsanity::InitializeFromSave();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "item_location.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "SeedContext.h"
|
||||
#include "logic.h"
|
||||
#include "rng.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "randomizer_check_objects.h"
|
||||
#include <libultraship/bridge/consolevariablebridge.h>
|
||||
#include "static_data.h"
|
||||
#include "SeedContext.h"
|
||||
#include <map>
|
||||
@@ -208,7 +209,7 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() {
|
||||
(location.GetRCType() != RCTYPE_RED_ICE ||
|
||||
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleRedIce"), RO_GENERIC_NO)) &&
|
||||
(location.GetRCType() != RCTYPE_FISH ||
|
||||
ctx->GetFishsanity()->GetFishLocationIncluded(&location, FSO_SOURCE_CVARS)) &&
|
||||
Rando::Fishsanity::GetFishLocationIncluded(&location, FSO_SOURCE_CVARS)) &&
|
||||
(location.GetRCType() != RCTYPE_ADULT_TRADE ||
|
||||
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), RO_GENERIC_NO)) &&
|
||||
(location.GetRandomizerCheck() != RC_KF_KOKIRI_SWORD_CHEST ||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "soh/SohGui/SohMenu.h"
|
||||
#include "dungeon.h"
|
||||
#include "entrance.h"
|
||||
#include "fishsanity.h"
|
||||
#include "location_access.h"
|
||||
#include "3drando/fill.hpp"
|
||||
#include "soh/Enhancements/debugger/performanceTimer.h"
|
||||
@@ -1945,8 +1946,7 @@ bool IsCheckShuffled(RandomizerCheck rc) {
|
||||
(showDungeonWonderItems && RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()))) &&
|
||||
(loc->GetRCType() != RCTYPE_ICICLE || showIcicles) &&
|
||||
(loc->GetRCType() != RCTYPE_RED_ICE || showRedIce) &&
|
||||
(loc->GetRCType() != RCTYPE_FISH ||
|
||||
OTRGlobals::Instance->gRandoContext->GetFishsanity()->GetFishLocationIncluded(loc)) &&
|
||||
(loc->GetRCType() != RCTYPE_FISH || Rando::Fishsanity::GetFishLocationIncluded(loc)) &&
|
||||
(loc->GetRCType() != RCTYPE_FREESTANDING ||
|
||||
(showOverworldFreestanding && RandomizerCheckObjects::AreaIsOverworld(loc->GetArea())) ||
|
||||
(showDungeonFreestanding && RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()))) &&
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "ResourceManagerHelpers.h"
|
||||
#include <libultraship/bridge/consolevariablebridge.h>
|
||||
#include "OTRGlobals.h"
|
||||
#include "variables.h"
|
||||
#include "z64.h"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include <unordered_set>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "SohMenu.h"
|
||||
#include "soh/Enhancements/enhancementTypes.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer_check_objects.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer.h"
|
||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||
#include "soh/Enhancements/randomizer/settings.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ShipUtils.h"
|
||||
#include "soh/SohGui/SohGui.hpp"
|
||||
|
||||
@@ -67,7 +67,7 @@ void SaveExcludedLocations() {
|
||||
}
|
||||
|
||||
void DrawLocationsMenu(WidgetInfo& info) {
|
||||
auto ctx = OTRGlobals::Instance->gRandoContext;
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
int32_t currMQDungeonSetting = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), 0) |
|
||||
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 0) << 8;
|
||||
static ImVec2 cellPadding(8.0f, 8.0f);
|
||||
@@ -360,7 +360,7 @@ void UpdateMenuTricks() {
|
||||
}
|
||||
|
||||
void DrawTricksMenu(WidgetInfo& info) {
|
||||
auto ctx = OTRGlobals::Instance->gRandoContext;
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
auto randoSettings = Rando::Settings::GetInstance();
|
||||
static ImVec2 cellPadding(8.0f, 8.0f);
|
||||
bool generating = CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0);
|
||||
@@ -717,7 +717,7 @@ void SohMenu::AddMenuRandomizer() {
|
||||
});
|
||||
AddWidget(path, "Generate Randomizer", WIDGET_BUTTON)
|
||||
.Callback([](WidgetInfo& info) {
|
||||
OTRGlobals::Instance->gRandoContext->SetSpoilerLoaded(false);
|
||||
Rando::Context::GetInstance()->SetSpoilerLoaded(false);
|
||||
GenerateRandomizer(CVarGetInteger(CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), 0) ? seedString : "");
|
||||
})
|
||||
.PreFunc([](WidgetInfo& info) {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#define FLAGS ACTOR_FLAG_UPDATE_CULLING_DISABLED
|
||||
#define WATER_SURFACE_Y(play) play->colCtx.colHeader->waterBoxes->ySurface
|
||||
bool getShouldSpawnLoaches();
|
||||
|
||||
void Fishing_Init(Actor* thisx, PlayState* play);
|
||||
void Fishing_Destroy(Actor* thisx, PlayState* play);
|
||||
@@ -432,13 +431,6 @@ static FishingEffect sFishingEffects[FISHING_EFFECT_COUNT];
|
||||
static Vec3f sStreamSoundProjectedPos;
|
||||
static s16 sFishOnHandParams;
|
||||
|
||||
f32 Fishing_GetMinimumRequiredScore();
|
||||
|
||||
u8 AllHyruleLoaches() {
|
||||
return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) &&
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("AllHyruleLoaches"), 0);
|
||||
}
|
||||
|
||||
void Fishing_SetColliderElement(s32 index, ColliderJntSph* collider, Vec3f* pos, f32 scale) {
|
||||
collider->elements[index].dim.worldSphere.center.x = pos->x;
|
||||
collider->elements[index].dim.worldSphere.center.y = pos->y;
|
||||
@@ -906,17 +898,13 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
|
||||
if (sLinkAge == LINK_AGE_CHILD) {
|
||||
if ((HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_CHILD) != 0) {
|
||||
sFishingRecordLength = HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_CHILD;
|
||||
} else if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0)) {
|
||||
sFishingRecordLength = Fishing_GetMinimumRequiredScore();
|
||||
} else {
|
||||
} else if (GameInteractor_Should(VB_FISHING_USE_DEFAULT_RECORD_LENGTH, true, &sFishingRecordLength)) {
|
||||
sFishingRecordLength = 40.0f; // 6 lbs
|
||||
}
|
||||
} else {
|
||||
if ((HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_ADULT) != 0) {
|
||||
sFishingRecordLength = (HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_ADULT) >> 0x18;
|
||||
} else if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0)) {
|
||||
sFishingRecordLength = Fishing_GetMinimumRequiredScore();
|
||||
} else {
|
||||
} else if (GameInteractor_Should(VB_FISHING_USE_DEFAULT_RECORD_LENGTH, true, &sFishingRecordLength)) {
|
||||
sFishingRecordLength = 45.0f; // 7 lbs
|
||||
}
|
||||
}
|
||||
@@ -991,8 +979,8 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
|
||||
ENKANBAN_FISHING);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_FISHING, 0.0f, 0.0f, 0.0f, 0, 0, 0, 200);
|
||||
|
||||
// Loach(es) will spawn every fourth game, or if "Loaches Always Appear" is enabled
|
||||
if (getShouldSpawnLoaches()) {
|
||||
// Loach(es) will spawn every fourth game
|
||||
if (GameInteractor_Should(VB_FISHING_SPAWN_LOACHES, (KREG(1) == 1) || ((sFishGameNumber & 3) == 3))) {
|
||||
// Fishes 16 and 17 are loaches. Only 16 is spawned as adult; child also spawns 17.
|
||||
if (sLinkAge != LINK_AGE_CHILD) {
|
||||
fishCount = 16;
|
||||
@@ -1008,7 +996,8 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
|
||||
sFishInits[i].pos.z, 0, Rand_ZeroFloat(0x10000), 0, 100 + i);
|
||||
}
|
||||
} else {
|
||||
if ((thisx->params < (EN_FISH_PARAM + 15) && !AllHyruleLoaches()) || (thisx->params == EN_FISH_AQUARIUM)) {
|
||||
if (!GameInteractor_Should(VB_FISHING_FISH_IS_LOACH, thisx->params >= (EN_FISH_PARAM + 15)) ||
|
||||
(thisx->params == EN_FISH_AQUARIUM)) {
|
||||
SkelAnime_InitFlex(play, &this->skelAnime, &gFishingFishSkel, &gFishingFishAnim, NULL, NULL, 0);
|
||||
Animation_MorphToLoop(&this->skelAnime, &gFishingFishAnim, 0.0f);
|
||||
} else {
|
||||
@@ -1028,7 +1017,8 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
|
||||
this->fishState = 10;
|
||||
this->fishStateNext = 10;
|
||||
|
||||
this->isLoach = sFishInits[thisx->params - EN_FISH_PARAM].isLoach || AllHyruleLoaches();
|
||||
this->isLoach =
|
||||
GameInteractor_Should(VB_FISHING_FISH_IS_LOACH, sFishInits[thisx->params - EN_FISH_PARAM].isLoach);
|
||||
this->perception = sFishInits[thisx->params - EN_FISH_PARAM].perception;
|
||||
this->fishLength = sFishInits[thisx->params - EN_FISH_PARAM].baseLength;
|
||||
|
||||
@@ -2910,49 +2900,6 @@ void Fishing_HandleAquariumDialog(Fishing* this, PlayState* play) {
|
||||
}
|
||||
}
|
||||
|
||||
f32 Fishing_GetMinimumRequiredScore() {
|
||||
int32_t weight;
|
||||
// RANDOTODO: update the enhancement sliders to not allow
|
||||
// values above rando fish weight values when rando'd
|
||||
if (sLinkAge == 1) {
|
||||
weight = CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0)
|
||||
? CVarGetInteger(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 10)
|
||||
: 10;
|
||||
} else {
|
||||
weight = CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0)
|
||||
? CVarGetInteger(CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 13)
|
||||
: 13;
|
||||
}
|
||||
|
||||
return sqrt(((f32)weight - 0.5f) / 0.0036f);
|
||||
}
|
||||
|
||||
bool getInstantFish() {
|
||||
return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) &&
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("InstantFishing"), 0);
|
||||
}
|
||||
|
||||
bool getGuaranteeBite() {
|
||||
return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) &&
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("GuaranteeFishingBite"), 0);
|
||||
}
|
||||
|
||||
bool getFishNeverEscape() {
|
||||
return CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) &&
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("FishNeverEscape"), 0);
|
||||
}
|
||||
|
||||
bool getShouldSpawnLoaches() {
|
||||
return (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) &&
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("LoachesAlwaysAppear"), 0)) ||
|
||||
((KREG(1) == 1) || ((sFishGameNumber & 3) == 3));
|
||||
}
|
||||
|
||||
bool getShouldConfirmKeep() {
|
||||
return !CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) ||
|
||||
!CVarGetInteger(CVAR_ENHANCEMENT("SkipKeepConfirmation"), 0);
|
||||
}
|
||||
|
||||
void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
|
||||
s16 i;
|
||||
s16 rotXYScale = 10;
|
||||
@@ -3451,9 +3398,9 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
|
||||
if (sLureEquipped == FS_LURE_SINKING) {
|
||||
chance *= 5.0f;
|
||||
}
|
||||
if (getGuaranteeBite() == 1 ||
|
||||
((this->timerArray[0] == 1) || (Rand_ZeroOne() < chance)) &&
|
||||
((Rand_ZeroOne() < (this->perception * multiplier)) || ((this->isLoach + 1) == KREG(69)))) {
|
||||
if (GameInteractor_Should(VB_FISHING_FISH_BITE, ((this->timerArray[0] == 1) || (Rand_ZeroOne() < chance)) &&
|
||||
((Rand_ZeroOne() < (this->perception * multiplier)) ||
|
||||
((this->isLoach + 1) == KREG(69))))) {
|
||||
if (this->isLoach == 0) {
|
||||
this->fishState = 3;
|
||||
this->unk_190 = 1.2f;
|
||||
@@ -3866,8 +3813,9 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
|
||||
|
||||
if ((sRodCastState < 3) || ((sReelLock != 0) && (sFishFightTime > 50)) || (sFishFightTime >= 6000) ||
|
||||
((sLureBitTimer == 0) && (sLineHooked == 0)) || (sRodPullback == 0) ||
|
||||
(((sLureTimer & 0x7F) == 0) && (Rand_ZeroOne() < 0.05f) && (sLureEquipped != FS_LURE_SINKING) &&
|
||||
(KREG(69) == 0) && (getFishNeverEscape() == 0))) {
|
||||
GameInteractor_Should(VB_FISHING_FISH_ESCAPE, ((sLureTimer & 0x7F) == 0) && (Rand_ZeroOne() < 0.05f) &&
|
||||
(sLureEquipped != FS_LURE_SINKING) &&
|
||||
(KREG(69) == 0))) {
|
||||
sFishingCaughtTextDelay = 20;
|
||||
|
||||
if ((sLureBitTimer == 0) && (sLineHooked == 0)) {
|
||||
@@ -3897,7 +3845,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
|
||||
sFishingMusicDelay = 50;
|
||||
sRodReelingSpeed = 0.5f;
|
||||
this->unk_152 = 0;
|
||||
} else if (this->actor.xzDistToPlayer < (KREG(59) + 50.0f) || getInstantFish() == 1) {
|
||||
} else if (GameInteractor_Should(VB_FISHING_CATCH_FISH, this->actor.xzDistToPlayer < (KREG(59) + 50.0f))) {
|
||||
this->fishState = 6;
|
||||
this->timerArray[0] = 100;
|
||||
player->unk_860 = 3;
|
||||
@@ -3976,7 +3924,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
|
||||
multiVecSrc.y = -10.0f;
|
||||
multiVecSrc.z = 5.0f;
|
||||
Matrix_MultVec3f(&multiVecSrc, &targetPosOffset);
|
||||
if (getInstantFish() == 0) {
|
||||
if (!GameInteractor_Should(VB_FISHING_INSTANT_CATCH, false)) {
|
||||
Math_ApproachF(&this->actor.world.pos.x, player->bodyPartsPos[15].x + targetPosOffset.x, 1.0f, 6.0f);
|
||||
Math_ApproachF(&this->actor.world.pos.y, player->bodyPartsPos[15].y + targetPosOffset.y, 1.0f, 6.0f);
|
||||
Math_ApproachF(&this->actor.world.pos.z, player->bodyPartsPos[15].z + targetPosOffset.z, 1.0f, 6.0f);
|
||||
@@ -4000,9 +3948,10 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
|
||||
sFishOnHandIsLoach = this->isLoach;
|
||||
sLureCaughtWith = sLureEquipped;
|
||||
Actor_Kill(&this->actor);
|
||||
} else if (getShouldConfirmKeep() && (this->isLoach == 0) &&
|
||||
(sFishOnHandIsLoach == 0) &&
|
||||
((s16)this->fishLength < (s16)sFishOnHandLength)) {
|
||||
} else if (GameInteractor_Should(
|
||||
VB_FISHING_CONFIRM_KEEPING_SMALLER_FISH,
|
||||
(this->isLoach == 0) && (sFishOnHandIsLoach == 0) &&
|
||||
((s16)this->fishLength < (s16)sFishOnHandLength))) {
|
||||
this->keepState = 1;
|
||||
this->timerArray[0] = 0x3C;
|
||||
Message_StartTextbox(play, 0x4098, NULL);
|
||||
@@ -5548,7 +5497,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
|
||||
player->actor.speedXZ = 0.0f;
|
||||
|
||||
// #region SOH [Enhancement]
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) {
|
||||
if (GameInteractor_Should(VB_FISHING_QUIT_AT_DOOR, false)) {
|
||||
Fishing_QuitAtDoor(this, play);
|
||||
}
|
||||
// #endregion
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include <libultraship/libultra.h>
|
||||
#include "global.h"
|
||||
#include "soh/Enhancements/randomizer/fishsanity.h"
|
||||
|
||||
struct Fishing;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user