mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-22 14:23:44 -07:00
Merge remote-tracking branch 'origin/develop' into actor-accessibility-experiments
This commit is contained in:
commit
e409f1fdc5
33 changed files with 460 additions and 299 deletions
48
soh/soh/Enhancements/DampeFire.cpp
Normal file
48
soh/soh/Enhancements/DampeFire.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "soh/Enhancements/enhancementTypes.h"
|
||||
|
||||
extern "C" {
|
||||
extern PlayState* gPlayState;
|
||||
#include "src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.h"
|
||||
}
|
||||
|
||||
void RegisterDampeFire() {
|
||||
COND_VB_SHOULD(VB_DAMPE_DROP_FLAME, CVarGetInteger(CVAR_ENHANCEMENT("DampeDropRate"), DAMPE_NORMAL) != DAMPE_NORMAL,
|
||||
{
|
||||
double chance;
|
||||
int cooldown = 9;
|
||||
switch (CVarGetInteger(CVAR_ENHANCEMENT("DampeDropRate"), DAMPE_NORMAL)) {
|
||||
case DAMPE_NONE:
|
||||
*should = false;
|
||||
return;
|
||||
default:
|
||||
case DAMPE_NORMAL:
|
||||
return;
|
||||
case DAMPE_JALAPENO:
|
||||
chance = 0.03;
|
||||
break;
|
||||
case DAMPE_CHIPOTLE:
|
||||
chance = 0.1;
|
||||
break;
|
||||
case DAMPE_SCOTCH_BONNET:
|
||||
chance = 0.2;
|
||||
break;
|
||||
case DAMPE_GHOST_PEPPER:
|
||||
chance = 0.5;
|
||||
cooldown = 4;
|
||||
break;
|
||||
case DAMPE_INFERNO:
|
||||
*should = true;
|
||||
return;
|
||||
}
|
||||
|
||||
EnPoRelay* actor = va_arg(args, EnPoRelay*);
|
||||
if (actor->actionTimer > cooldown) {
|
||||
actor->actionTimer = cooldown;
|
||||
}
|
||||
*should = actor->actionTimer == 0 && Rand_ZeroOne() < chance;
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterDampeFire, { CVAR_ENHANCEMENT("DampeDropRate") });
|
50
soh/soh/Enhancements/ExtraModes/ShadowTag.cpp
Normal file
50
soh/soh/Enhancements/ExtraModes/ShadowTag.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#include <libultraship/bridge.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "functions.h"
|
||||
|
||||
extern "C" PlayState* gPlayState;
|
||||
|
||||
static constexpr int32_t CVAR_SHADOW_TAG_DEFAULT = 0;
|
||||
#define CVAR_SHADOW_TAG_NAME CVAR_ENHANCEMENT("ShadowTag")
|
||||
#define CVAR_SHADOW_TAG_VALUE CVarGetInteger(CVAR_SHADOW_TAG_NAME, CVAR_SHADOW_TAG_DEFAULT)
|
||||
|
||||
static bool shouldSpawn = false;
|
||||
static uint16_t delayTimer = 60;
|
||||
|
||||
static constexpr s8 ROOM_GREEN_POE = 16;
|
||||
static constexpr s8 ROOM_BLUE_POE = 13;
|
||||
static constexpr s8 ROOM_RED_POE = 12;
|
||||
|
||||
void OnPlayerUpdateShadowTag() {
|
||||
if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE) {
|
||||
switch (gPlayState->roomCtx.curRoom.num) {
|
||||
case ROOM_GREEN_POE:
|
||||
case ROOM_BLUE_POE:
|
||||
case ROOM_RED_POE:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSpawn && (delayTimer <= 0)) {
|
||||
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_WALLMAS, 0, 0, 0, 0, 0, 0, 3, false);
|
||||
shouldSpawn = false;
|
||||
} else {
|
||||
delayTimer--;
|
||||
}
|
||||
}
|
||||
|
||||
void ResetShadowTagSpawnTimer() {
|
||||
shouldSpawn = true;
|
||||
delayTimer = 60;
|
||||
}
|
||||
|
||||
void RegisterShadowTag() {
|
||||
COND_HOOK(OnPlayerUpdate, CVAR_SHADOW_TAG_VALUE, OnPlayerUpdateShadowTag);
|
||||
COND_HOOK(OnSceneSpawnActors, true, []() { ResetShadowTagSpawnTimer(); });
|
||||
COND_HOOK(OnSceneInit, true, [](int16_t) { ResetShadowTagSpawnTimer(); });
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc_ShadowTag(RegisterShadowTag, { CVAR_SHADOW_TAG_NAME });
|
|
@ -316,7 +316,7 @@ const std::vector<PresetEntry> randomizerBeginnerPresetEntries = {
|
|||
|
||||
// Gamplay tab
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
||||
|
@ -387,7 +387,7 @@ const std::vector<PresetEntry> randomizerStandardPresetEntries = {
|
|||
|
||||
// Gamplay tab
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
||||
|
@ -469,7 +469,7 @@ const std::vector<PresetEntry> randomizerAdvancedPresetEntries = {
|
|||
|
||||
// Gamplay tab
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
||||
|
@ -568,7 +568,7 @@ const std::vector<PresetEntry> hellModePresetEntries = {
|
|||
|
||||
// Gamplay tab
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),
|
||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1),
|
||||
|
|
70
soh/soh/Enhancements/QoL/DaytimeGS.cpp
Normal file
70
soh/soh/Enhancements/QoL/DaytimeGS.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include <libultraship/bridge.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
|
||||
extern "C" {
|
||||
extern PlayState* gPlayState;
|
||||
extern SaveContext gSaveContext;
|
||||
}
|
||||
|
||||
static constexpr int32_t CVAR_DAYTIME_GS_DEFAULT = 0;
|
||||
#define CVAR_DAYTIME_GS_NAME CVAR_ENHANCEMENT("NightGSAlwaysSpawn")
|
||||
#define CVAR_DAYTIME_GS_VALUE CVarGetInteger(CVAR_DAYTIME_GS_NAME, CVAR_DAYTIME_GS_DEFAULT)
|
||||
|
||||
struct DayTimeGoldSkulltulas {
|
||||
uint16_t scene;
|
||||
uint16_t room;
|
||||
bool forChild;
|
||||
std::vector<ActorEntry> actorEntries;
|
||||
};
|
||||
|
||||
using DayTimeGoldSkulltulasList = std::vector<DayTimeGoldSkulltulas>;
|
||||
|
||||
void OnSpawnNighttimeGoldSkulltula() {
|
||||
// Gold Skulltulas that are not part of the scene actor list during the day
|
||||
// Actor values copied from the night time scene actor list
|
||||
static const DayTimeGoldSkulltulasList dayTimeGoldSkulltulas = {
|
||||
// Graveyard
|
||||
{ SCENE_GRAVEYARD, 1, true, { { ACTOR_EN_SW, { 156, 315, 795 }, { 16384, -32768, 0 }, -20096 } } },
|
||||
// ZF
|
||||
{ SCENE_ZORAS_FOUNTAIN, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } },
|
||||
// GF
|
||||
{ SCENE_GERUDOS_FORTRESS, 0, false, { { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } },
|
||||
{ SCENE_GERUDOS_FORTRESS, 1, false, { { ACTOR_EN_SW, { 3377, 1734, -4935 }, { 16384, 0, 0 }, -19199 } } },
|
||||
// Kak
|
||||
{ SCENE_KAKARIKO_VILLAGE, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } },
|
||||
{ SCENE_KAKARIKO_VILLAGE,
|
||||
0,
|
||||
true,
|
||||
{ { ACTOR_EN_SW, { -465, 377, -888 }, { 0, 28217, 0 }, -20222 },
|
||||
{ ACTOR_EN_SW, { 5, 686, -171 }, { 0, -32768, 0 }, -20220 },
|
||||
{ ACTOR_EN_SW, { 324, 270, 905 }, { 16384, 0, 0 }, -20216 },
|
||||
{ ACTOR_EN_SW, { -602, 120, 1120 }, { 16384, 0, 0 }, -20208 } } },
|
||||
// LLR
|
||||
{ SCENE_LON_LON_RANCH,
|
||||
0,
|
||||
true,
|
||||
{ { ACTOR_EN_SW, { -2344, 180, 672 }, { 16384, 22938, 0 }, -29695 },
|
||||
{ ACTOR_EN_SW, { 808, 48, 326 }, { 16384, 0, 0 }, -29694 },
|
||||
{ ACTOR_EN_SW, { 997, 286, -2698 }, { 16384, -16384, 0 }, -29692 } } },
|
||||
};
|
||||
|
||||
for (const auto& dayTimeGS : dayTimeGoldSkulltulas) {
|
||||
if (IS_DAY && dayTimeGS.forChild == LINK_IS_CHILD && dayTimeGS.scene == gPlayState->sceneNum &&
|
||||
dayTimeGS.room == gPlayState->roomCtx.curRoom.num) {
|
||||
for (const auto& actorEntry : dayTimeGS.actorEntries) {
|
||||
Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorEntry.id, actorEntry.pos.x, actorEntry.pos.y,
|
||||
actorEntry.pos.z, actorEntry.rot.x, actorEntry.rot.y, actorEntry.rot.z, actorEntry.params,
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterDaytimeGoldSkultullas() {
|
||||
COND_HOOK(OnSceneSpawnActors, CVAR_DAYTIME_GS_VALUE, OnSpawnNighttimeGoldSkulltula);
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc_DaytimeGoldSkulltulas(RegisterDaytimeGoldSkultullas, { CVAR_DAYTIME_GS_NAME });
|
|
@ -162,6 +162,7 @@ typedef enum {
|
|||
TEXT_ANJU_THANKS_FOR_FINDING_MY_CUCCOS = 0x503B,
|
||||
TEXT_ANJU_ROUND_THEM_UP_OR_YOULL_PAY = 0x503C,
|
||||
TEXT_ANJU_DONT_TEASE_MY_CUCCOS = 0x503D,
|
||||
TEXT_BIG_POE_COLLECTED_RANDO = 0x5090,
|
||||
TEXT_HBA_NOT_ON_HORSE = 0x603F,
|
||||
TEXT_HBA_INITIAL_EXPLAINATION = 0x6040,
|
||||
TEXT_HBA_WANT_TO_TRY_AGAIN_YES_NO = 0x6041,
|
||||
|
|
|
@ -87,6 +87,16 @@ typedef enum {
|
|||
DAMAGE_OHKO
|
||||
} DamageMultType;
|
||||
|
||||
typedef enum {
|
||||
DAMPE_NONE,
|
||||
DAMPE_NORMAL,
|
||||
DAMPE_JALAPENO,
|
||||
DAMPE_CHIPOTLE,
|
||||
DAMPE_SCOTCH_BONNET,
|
||||
DAMPE_GHOST_PEPPER,
|
||||
DAMPE_INFERNO,
|
||||
} DampeDropRate;
|
||||
|
||||
typedef enum {
|
||||
DEKU_STICK_NORMAL,
|
||||
DEKU_STICK_UNBREAKABLE,
|
||||
|
|
|
@ -228,6 +228,14 @@ typedef enum {
|
|||
// - `*Actor` (interactRangeActor)
|
||||
VB_BOTTLE_ACTOR,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*EnPoField`
|
||||
VB_BOTTLE_BIG_POE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// ((this->actor.params == DNS_TYPE_HEART_PIECE) && (Flags_GetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE))) ||
|
||||
|
@ -331,6 +339,14 @@ typedef enum {
|
|||
// - None
|
||||
VB_CRAWL_SPEED_INCREASE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// this->actionTimer == 0 && Rand_ZeroOne() < 0.03f
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*EnPoRelay`
|
||||
VB_DAMPE_DROP_FLAME,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// !Flags_GetItemGetInf(ITEMGETINF_1C)
|
||||
|
@ -1733,6 +1749,14 @@ typedef enum {
|
|||
// - `*EnRu1`
|
||||
VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*EnGb`
|
||||
VB_SELL_POES_TO_POE_COLLECTOR,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
|
|
|
@ -159,38 +159,6 @@ void RegisterRupeeDash() {
|
|||
});
|
||||
}
|
||||
|
||||
void RegisterShadowTag() {
|
||||
static bool shouldSpawn = false;
|
||||
static uint16_t delayTimer = 60;
|
||||
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("ShadowTag"), 0)) {
|
||||
return;
|
||||
}
|
||||
if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && // Forest Temple Scene
|
||||
gPlayState->roomCtx.curRoom.num == 16 || // Green Poe Room
|
||||
gPlayState->roomCtx.curRoom.num == 13 || // Blue Poe Room
|
||||
gPlayState->roomCtx.curRoom.num == 12) { // Red Poe Room
|
||||
return;
|
||||
} else {
|
||||
if (shouldSpawn && (delayTimer <= 0)) {
|
||||
Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_WALLMAS, 0, 0, 0, 0, 0, 0, 3, false);
|
||||
shouldSpawn = false;
|
||||
} else {
|
||||
delayTimer--;
|
||||
}
|
||||
}
|
||||
});
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneSpawnActors>([]() {
|
||||
shouldSpawn = true;
|
||||
delayTimer = 60;
|
||||
});
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
|
||||
shouldSpawn = true;
|
||||
delayTimer = 60;
|
||||
});
|
||||
}
|
||||
|
||||
static bool hasAffectedHealth = false;
|
||||
void UpdatePermanentHeartLossState() {
|
||||
if (!GameInteractor::IsSaveLoaded())
|
||||
|
@ -243,65 +211,6 @@ void RegisterDeleteFileOnDeath() {
|
|||
});
|
||||
}
|
||||
|
||||
struct DayTimeGoldSkulltulas {
|
||||
uint16_t scene;
|
||||
uint16_t room;
|
||||
bool forChild;
|
||||
std::vector<ActorEntry> actorEntries;
|
||||
};
|
||||
|
||||
using DayTimeGoldSkulltulasList = std::vector<DayTimeGoldSkulltulas>;
|
||||
|
||||
void RegisterDaytimeGoldSkultullas() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneSpawnActors>([]() {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("NightGSAlwaysSpawn"), 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Gold Skulltulas that are not part of the scene actor list during the day
|
||||
// Actor values copied from the night time scene actor list
|
||||
static const DayTimeGoldSkulltulasList dayTimeGoldSkulltulas = {
|
||||
// Graveyard
|
||||
{ SCENE_GRAVEYARD, 1, true, { { ACTOR_EN_SW, { 156, 315, 795 }, { 16384, -32768, 0 }, -20096 } } },
|
||||
// ZF
|
||||
{ SCENE_ZORAS_FOUNTAIN, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } },
|
||||
// GF
|
||||
{ SCENE_GERUDOS_FORTRESS,
|
||||
0,
|
||||
false,
|
||||
{ { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } },
|
||||
{ SCENE_GERUDOS_FORTRESS, 1, false, { { ACTOR_EN_SW, { 3377, 1734, -4935 }, { 16384, 0, 0 }, -19199 } } },
|
||||
// Kak
|
||||
{ SCENE_KAKARIKO_VILLAGE, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } },
|
||||
{ SCENE_KAKARIKO_VILLAGE,
|
||||
0,
|
||||
true,
|
||||
{ { ACTOR_EN_SW, { -465, 377, -888 }, { 0, 28217, 0 }, -20222 },
|
||||
{ ACTOR_EN_SW, { 5, 686, -171 }, { 0, -32768, 0 }, -20220 },
|
||||
{ ACTOR_EN_SW, { 324, 270, 905 }, { 16384, 0, 0 }, -20216 },
|
||||
{ ACTOR_EN_SW, { -602, 120, 1120 }, { 16384, 0, 0 }, -20208 } } },
|
||||
// LLR
|
||||
{ SCENE_LON_LON_RANCH,
|
||||
0,
|
||||
true,
|
||||
{ { ACTOR_EN_SW, { -2344, 180, 672 }, { 16384, 22938, 0 }, -29695 },
|
||||
{ ACTOR_EN_SW, { 808, 48, 326 }, { 16384, 0, 0 }, -29694 },
|
||||
{ ACTOR_EN_SW, { 997, 286, -2698 }, { 16384, -16384, 0 }, -29692 } } },
|
||||
};
|
||||
|
||||
for (const auto& dayTimeGS : dayTimeGoldSkulltulas) {
|
||||
if (IS_DAY && dayTimeGS.forChild == LINK_IS_CHILD && dayTimeGS.scene == gPlayState->sceneNum &&
|
||||
dayTimeGS.room == gPlayState->roomCtx.curRoom.num) {
|
||||
for (const auto& actorEntry : dayTimeGS.actorEntries) {
|
||||
Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorEntry.id, actorEntry.pos.x, actorEntry.pos.y,
|
||||
actorEntry.pos.z, actorEntry.rot.x, actorEntry.rot.y, actorEntry.rot.z,
|
||||
actorEntry.params, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool IsHyperBossesActive() {
|
||||
return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) ||
|
||||
(IS_BOSS_RUSH &&
|
||||
|
@ -1073,9 +982,7 @@ void InitMods() {
|
|||
TimeSavers_Register();
|
||||
RegisterTTS();
|
||||
RegisterOcarinaTimeTravel();
|
||||
RegisterDaytimeGoldSkultullas();
|
||||
RegisterRupeeDash();
|
||||
RegisterShadowTag();
|
||||
RegisterPermanentHeartLoss();
|
||||
RegisterDeleteFileOnDeath();
|
||||
RegisterHyperBosses();
|
||||
|
|
|
@ -159,11 +159,6 @@ static void ValidateOtherEntrance(GetAccessibleLocationsStruct& gals) {
|
|||
ApplyStartingInventory(); // RANDOTODO when proper ammo logic is done, this could be moved to the start
|
||||
}
|
||||
}
|
||||
// If we are not shuffling the guard house, add the key so we can properly check for poe merchant access
|
||||
if (gals.validatedStartingRegion && gals.foundTempleOfTime &&
|
||||
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF)) {
|
||||
Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect();
|
||||
}
|
||||
}
|
||||
|
||||
// Apply all items that are necessary for checking all location access
|
||||
|
@ -180,10 +175,7 @@ static void ApplyAllAdvancmentItems() {
|
|||
static void ValidateSphereZero(GetAccessibleLocationsStruct& gals) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
// Condition for verifying everything required for sphere 0, expanding search to all locations
|
||||
if ((!logic->AreCheckingBigPoes || logic->CanEmptyBigPoes) && gals.validatedStartingRegion &&
|
||||
gals.foundTempleOfTime && gals.haveTimeAccess) {
|
||||
// stop checking for big poes
|
||||
logic->AreCheckingBigPoes = false;
|
||||
if (gals.validatedStartingRegion && gals.foundTempleOfTime && gals.haveTimeAccess) {
|
||||
// Apply all items that are necessary for checking all location access
|
||||
ApplyAllAdvancmentItems();
|
||||
// Reset access as the non-starting age
|
||||
|
@ -213,7 +205,7 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer
|
|||
// Update Time of Day Access for the exit
|
||||
if (UpdateToDAccess(&exit, exitRegion)) {
|
||||
gals.logicUpdated = true;
|
||||
if (!gals.sphereZeroComplete || logic->AreCheckingBigPoes) {
|
||||
if (!gals.sphereZeroComplete) {
|
||||
if (!gals.foundTempleOfTime || !gals.validatedStartingRegion) {
|
||||
ValidateOtherEntrance(gals);
|
||||
}
|
||||
|
@ -596,15 +588,12 @@ bool CheckBeatable(RandomizerGet ignore /* = RG_NONE*/) {
|
|||
}
|
||||
|
||||
// Check if the currently randomised set of entrances is a valid game map.
|
||||
void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAccess) {
|
||||
void ValidateEntrances(bool checkOtherEntranceAccess) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
GetAccessibleLocationsStruct gals(0);
|
||||
ResetLogic(ctx, gals, !checkOtherEntranceAccess);
|
||||
|
||||
ctx->allLocationsReachable = false;
|
||||
if (checkPoeCollectorAccess) {
|
||||
logic->AreCheckingBigPoes = true;
|
||||
}
|
||||
|
||||
if (checkOtherEntranceAccess) {
|
||||
gals.foundTempleOfTime = false;
|
||||
|
@ -620,13 +609,6 @@ void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAcce
|
|||
RegionTable(RR_ROOT)->adultNight = true;
|
||||
RegionTable(RR_ROOT)->childDay = true;
|
||||
RegionTable(RR_ROOT)->adultDay = true;
|
||||
} else if (checkPoeCollectorAccess) {
|
||||
// If we are not shuffling the guard house, add the key so we can properly check for poe merchant access
|
||||
if (ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF)) {
|
||||
Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect();
|
||||
}
|
||||
RegionTable(RR_ROOT)->adultNight = true;
|
||||
RegionTable(RR_ROOT)->adultDay = true;
|
||||
} else {
|
||||
ApplyAllAdvancmentItems();
|
||||
}
|
||||
|
|
|
@ -72,4 +72,4 @@ void GeneratePlaythrough();
|
|||
|
||||
bool CheckBeatable(RandomizerGet ignore = RG_NONE);
|
||||
|
||||
void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAccess);
|
||||
void ValidateEntrances(bool checkOtherEntranceAccess);
|
||||
|
|
|
@ -273,8 +273,8 @@ std::vector<std::pair<RandomizerCheck, std::function<bool()>>> conditionalAlways
|
|||
std::make_pair(RC_MARKET_10_BIG_POES,
|
||||
[]() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
return ctx->GetOption(RSK_BIG_POE_COUNT).Get() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
|
||||
}), // Remember, the option's value being 3 means 4 are required
|
||||
return ctx->GetOption(RSK_BIG_POE_COUNT).Get() > 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
|
||||
}),
|
||||
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH,
|
||||
[]() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
|
|
137
soh/soh/Enhancements/randomizer/ShuffleBeehives.cpp
Normal file
137
soh/soh/Enhancements/randomizer/ShuffleBeehives.cpp
Normal file
|
@ -0,0 +1,137 @@
|
|||
#include <soh/OTRGlobals.h>
|
||||
#include "static_data.h"
|
||||
|
||||
extern "C" {
|
||||
#include "src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h"
|
||||
extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
|
||||
|
||||
void ObjComb_RandomizerChooseItemDrop(ObjComb* objComb, PlayState* play) {
|
||||
s16 params = objComb->actor.params & 0x1F;
|
||||
|
||||
if (Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_BEEHIVES).Get() &&
|
||||
!Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf)) {
|
||||
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &objComb->actor.world.pos, ITEM00_SOH_DUMMY);
|
||||
item00->randoInf = objComb->beehiveIdentity.randomizerInf;
|
||||
item00->itemEntry =
|
||||
OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(objComb->beehiveIdentity.randomizerCheck, GI_NONE);
|
||||
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((params > 0) || (params < 0x1A)) {
|
||||
if (params == 6) {
|
||||
if (Flags_GetCollectible(play, (objComb->actor.params >> 8) & 0x3F)) {
|
||||
params = -1;
|
||||
} else {
|
||||
params = (params | (((objComb->actor.params >> 8) & 0x3F) << 8));
|
||||
}
|
||||
} else if (Rand_ZeroOne() < 0.5f) {
|
||||
params = -1;
|
||||
}
|
||||
if (params >= 0 && !CVarGetInteger(CVAR_ENHANCEMENT("NoRandomDrops"), 0)) {
|
||||
Item_DropCollectible(play, &objComb->actor.world.pos, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjComb_RandomizerWait(ObjComb* objComb, PlayState* play) {
|
||||
s32 dmgFlags;
|
||||
|
||||
objComb->unk_1B0 -= 50;
|
||||
if (Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_BEEHIVES).Get() &&
|
||||
!Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf)) {
|
||||
if (objComb->unk_1B0 <= -5000) {
|
||||
objComb->unk_1B0 = 1500;
|
||||
}
|
||||
} else if (objComb->unk_1B0 < 0) {
|
||||
objComb->unk_1B0 = 0;
|
||||
}
|
||||
|
||||
if ((objComb->collider.base.acFlags & AC_HIT) != 0) {
|
||||
objComb->collider.base.acFlags &= ~AC_HIT;
|
||||
dmgFlags = objComb->collider.elements[0].info.acHitInfo->toucher.dmgFlags;
|
||||
if (dmgFlags & 0x4001F866) {
|
||||
objComb->unk_1B0 = 1500;
|
||||
} else {
|
||||
ObjComb_Break(objComb, play);
|
||||
ObjComb_RandomizerChooseItemDrop(objComb, play);
|
||||
Actor_Kill(&objComb->actor);
|
||||
}
|
||||
} else {
|
||||
CollisionCheck_SetAC(play, &play->colChkCtx, &objComb->collider.base);
|
||||
}
|
||||
|
||||
if (objComb->actor.update != NULL) {
|
||||
CollisionCheck_SetOC(play, &play->colChkCtx, &objComb->collider.base);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjComb_RandomizerInit(void* actor) {
|
||||
ObjComb* objComb = static_cast<ObjComb*>(actor);
|
||||
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
|
||||
objComb->beehiveIdentity = OTRGlobals::Instance->gRandomizer->IdentifyBeehive(
|
||||
gPlayState->sceneNum, (s16)objComb->actor.world.pos.x, respawnData);
|
||||
objComb->actionFunc = (ObjCombActionFunc)ObjComb_RandomizerWait;
|
||||
}
|
||||
|
||||
void ObjComb_RandomizerUpdate(void* actor) {
|
||||
ObjComb* combActor = reinterpret_cast<ObjComb*>(actor);
|
||||
combActor->actor.shape.rot.x =
|
||||
static_cast<int16_t>(Math_SinS(combActor->unk_1B2)) * CLAMP_MIN(combActor->unk_1B0, 0) +
|
||||
combActor->actor.home.rot.x;
|
||||
}
|
||||
|
||||
void RegisterShuffleBeehives() {
|
||||
bool shouldRegister = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_BEEHIVES).Get();
|
||||
|
||||
COND_ID_HOOK(OnActorInit, ACTOR_OBJ_COMB, shouldRegister, ObjComb_RandomizerInit);
|
||||
COND_ID_HOOK(OnActorUpdate, ACTOR_OBJ_COMB, shouldRegister, ObjComb_RandomizerUpdate);
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterShuffleBeehives, { "IS_RANDO" });
|
||||
|
||||
void Rando::StaticData::RegisterBeehiveLocations() {
|
||||
static bool registered = false;
|
||||
if (registered)
|
||||
return;
|
||||
registered = true;
|
||||
// clang-format off
|
||||
locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x2C), "Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_LEFT));
|
||||
locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x2C), "Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_RIGHT));
|
||||
locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x14), "Tunnel Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_LEFT));
|
||||
locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x14), "Tunnel Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_RIGHT));
|
||||
locationTable[RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(747, 0xF5), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_DEKU_SCRUB_GROTTO));
|
||||
locationTable[RC_SFM_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_SFM_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_SACRED_FOREST_MEADOW, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEE), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_SFM_STORMS_GROTTO));
|
||||
locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x00), "Near Market Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_LEFT));
|
||||
locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x00), "Near Market Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_RIGHT));
|
||||
locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x03), "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_LEFT));
|
||||
locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x03), "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_RIGHT));
|
||||
locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x22), "Southeast Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_LEFT));
|
||||
locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x22), "Southeast Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_RIGHT));
|
||||
locationTable[RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE] = Location::Base(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1410, 0xE6), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_LONELY_SCRUB_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_INSIDE_FENCE_GROTTO));
|
||||
locationTable[RC_LLR_GROTTO_BEEHIVE] = Location::Base(RC_LLR_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LON_LON_RANCH, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFC), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LLR_GROTTO));
|
||||
locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x28), "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_LEFT));
|
||||
locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x28), "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_RIGHT));
|
||||
locationTable[RC_DMT_COW_GROTTO_BEEHIVE] = Location::Base(RC_DMT_COW_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2617, 0xF8), "Cow Grotto Beehive", RHT_BEEHIVE_COW_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_COW_GROTTO));
|
||||
locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x57), "Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_LEFT));
|
||||
locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x57), "Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_RIGHT));
|
||||
locationTable[RC_GC_GROTTO_BEEHIVE] = Location::Base(RC_GC_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GORON_CITY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFB), "Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GC_GROTTO));
|
||||
locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x7A), "Upper Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_LEFT));
|
||||
locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x7A), "Upper Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_RIGHT));
|
||||
locationTable[RC_DMC_HAMMER_GROTTO_BEEHIVE] = Location::Base(RC_DMC_HAMMER_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xF9), "Hammer Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_HAMMER_GROTTO));
|
||||
locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x29), "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_LEFT));
|
||||
locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x29), "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_RIGHT));
|
||||
locationTable[RC_ZR_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_ZR_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEB), "Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_STORMS_GROTTO));
|
||||
locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(382, 0x00), "In Front of King Zora Beehive Left", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_LEFT));
|
||||
locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(948, 0x00), "In Front of King Zora Beehive Right", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_RIGHT));
|
||||
locationTable[RC_ZD_BEHIND_KING_ZORA_BEEHIVE] = Location::Base(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(701, 0x00), "Behind King Zora Beehive", RHT_BEEHIVE_BEHIND_KING_ZORA, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_BEHIND_KING_ZORA));
|
||||
locationTable[RC_LH_GROTTO_BEEHIVE] = Location::Base(RC_LH_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LAKE_HYLIA, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xEF), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LH_GROTTO));
|
||||
locationTable[RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GERUDO_VALLEY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xF0), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GV_DEKU_SCRUB_GROTTO));
|
||||
locationTable[RC_COLOSSUS_GROTTO_BEEHIVE] = Location::Base(RC_COLOSSUS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DESERT_COLOSSUS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xFD), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_COLOSSUS_GROTTO));
|
||||
// clang-format-on
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc registerFunc(Rando::StaticData::RegisterBeehiveLocations);
|
|
@ -76,7 +76,6 @@ void Rando::StaticData::RegisterCowLocations() {
|
|||
locationTable[RC_DMT_COW_GROTTO_COW] = Location::Base(RC_DMT_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2444, -471), "Cow Grotto Cow", RHT_DMT_COW_GROTTO_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW));
|
||||
locationTable[RC_GV_COW] = Location::Base(RC_GV_COW, RCQUEST_BOTH, RCTYPE_COW, ACTOR_EN_COW, SCENE_GERUDO_VALLEY, 0x00, "Cow", RHT_GV_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_GV_COW));
|
||||
locationTable[RC_JABU_JABUS_BELLY_MQ_COW] = Location::Base(RC_JABU_JABUS_BELLY_MQ_COW, RCQUEST_MQ, RCTYPE_COW, ACTOR_EN_COW, SCENE_JABU_JABU, 0x00, "MQ Cow", RHT_JABU_JABUS_BELLY_MQ_COW, RG_MILK, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW));
|
||||
|
||||
// clang-format-on
|
||||
}
|
||||
|
||||
|
|
|
@ -202,7 +202,6 @@ void Context::GenerateLocationPool() {
|
|||
mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_DUNGEONS)) ||
|
||||
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_DUNGEONS)) ||
|
||||
(location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_DUNGEONS)) ||
|
||||
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_DUNGEONS)) ||
|
||||
(location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS)) ||
|
||||
(location.GetRCType() == RCTYPE_NLCRATE &&
|
||||
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS) &&
|
||||
|
|
|
@ -441,12 +441,6 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
|||
type = entrancePlaced->GetType();
|
||||
}
|
||||
|
||||
bool checkPoeCollectorAccess =
|
||||
(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) ||
|
||||
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL)) &&
|
||||
(entrancePlaced == nullptr || ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS) || type == EntranceType::Interior ||
|
||||
type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn ||
|
||||
type == EntranceType::WarpSong || type == EntranceType::OwlDrop);
|
||||
bool checkOtherEntranceAccess =
|
||||
(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) ||
|
||||
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL) ||
|
||||
|
@ -459,7 +453,7 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
|||
// Conditions will be checked during the search and any that fail will be figured out
|
||||
// afterwards
|
||||
ctx->GetLogic()->Reset();
|
||||
ValidateEntrances(checkPoeCollectorAccess, checkOtherEntranceAccess);
|
||||
ValidateEntrances(checkOtherEntranceAccess);
|
||||
|
||||
if (!ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||
// Unless entrances are decoupled, we don't want the player to end up through certain entrances as the wrong age
|
||||
|
@ -544,15 +538,6 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
|||
}
|
||||
}
|
||||
|
||||
// The Big Poe shop should always be accessible as adult without the need to use any bottles
|
||||
// This is important to ensure that players can never lock their only bottles by filling them with Big Poes they
|
||||
// can't sell
|
||||
if (checkPoeCollectorAccess) {
|
||||
if (!RegionTable(RR_MARKET_GUARD_HOUSE)->Adult()) {
|
||||
SPDLOG_DEBUG("Big Poe Shop access is not guarenteed as adult\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
SPDLOG_DEBUG("All Locations NOT REACHABLE\n");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ extern "C" {
|
|||
#include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h"
|
||||
#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h"
|
||||
#include "src/overlays/actors/ovl_En_Gb/z_en_gb.h"
|
||||
#include "src/overlays/actors/ovl_En_Po_Field/z_en_po_field.h"
|
||||
#include "src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h"
|
||||
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
|
||||
#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h"
|
||||
|
@ -43,7 +44,6 @@ extern "C" {
|
|||
#include "src/overlays/actors/ovl_En_Box/z_en_box.h"
|
||||
#include "src/overlays/actors/ovl_En_Skj/z_en_skj.h"
|
||||
#include "src/overlays/actors/ovl_En_Hy/z_en_hy.h"
|
||||
#include "src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h"
|
||||
#include "src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h"
|
||||
#include "src/overlays/actors/ovl_En_Ge1/z_en_ge1.h"
|
||||
#include "src/overlays/actors/ovl_En_Ds/z_en_ds.h"
|
||||
|
@ -1080,12 +1080,35 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
|
|||
*should = false;
|
||||
break;
|
||||
}
|
||||
case VB_BOTTLE_BIG_POE: {
|
||||
EnPoField* enPoe = va_arg(args, EnPoField*);
|
||||
enPoe->actor.textId = 0x5090;
|
||||
Flags_SetSwitch(gPlayState, enPoe->actor.params & 0xFF);
|
||||
HIGH_SCORE(HS_POE_POINTS) += 100;
|
||||
if (HIGH_SCORE(HS_POE_POINTS) > 1100) {
|
||||
HIGH_SCORE(HS_POE_POINTS) = 1100;
|
||||
}
|
||||
*should = false;
|
||||
break;
|
||||
}
|
||||
case VB_SELL_POES_TO_POE_COLLECTOR: {
|
||||
if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES) && HIGH_SCORE(HS_POE_POINTS) >= 1000) {
|
||||
EnGb* enGb = va_arg(args, EnGb*);
|
||||
enGb->textId = 0x70F8;
|
||||
Message_ContinueTextbox(gPlayState, enGb->textId);
|
||||
enGb->actionFunc = func_80A2FB40;
|
||||
*should = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VB_GIVE_ITEM_FROM_POE_COLLECTOR: {
|
||||
EnGb* enGb = va_arg(args, EnGb*);
|
||||
if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES)) {
|
||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET);
|
||||
Flags_SetRandomizerInf(RAND_INF_10_BIG_POES);
|
||||
enGb->textId = 0x70F5;
|
||||
enGb->dyna.actor.parent = NULL;
|
||||
enGb->actionFunc = func_80A2FC0C;
|
||||
enGb->actionFunc = func_80A2F83C;
|
||||
*should = false;
|
||||
}
|
||||
break;
|
||||
|
@ -1832,65 +1855,6 @@ void EnDns_RandomizerPurchase(EnDns* enDns) {
|
|||
Flags_SetRandomizerInf(enDns->sohScrubIdentity.randomizerInf);
|
||||
}
|
||||
|
||||
void ObjComb_RandomizerChooseItemDrop(ObjComb* objComb, PlayState* play) {
|
||||
s16 params = objComb->actor.params & 0x1F;
|
||||
|
||||
if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf)) {
|
||||
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &objComb->actor.world.pos, ITEM00_SOH_DUMMY);
|
||||
item00->randoInf = objComb->beehiveIdentity.randomizerInf;
|
||||
item00->itemEntry =
|
||||
OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(objComb->beehiveIdentity.randomizerCheck, GI_NONE);
|
||||
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((params > 0) || (params < 0x1A)) {
|
||||
if (params == 6) {
|
||||
if (Flags_GetCollectible(play, (objComb->actor.params >> 8) & 0x3F)) {
|
||||
params = -1;
|
||||
} else {
|
||||
params = (params | (((objComb->actor.params >> 8) & 0x3F) << 8));
|
||||
}
|
||||
} else if (Rand_ZeroOne() < 0.5f) {
|
||||
params = -1;
|
||||
}
|
||||
if (params >= 0 && !CVarGetInteger(CVAR_ENHANCEMENT("NoRandomDrops"), 0)) {
|
||||
Item_DropCollectible(play, &objComb->actor.world.pos, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjComb_RandomizerWait(ObjComb* objComb, PlayState* play) {
|
||||
s32 dmgFlags;
|
||||
|
||||
objComb->unk_1B0 -= 50;
|
||||
if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf)) {
|
||||
if (objComb->unk_1B0 <= -5000) {
|
||||
objComb->unk_1B0 = 1500;
|
||||
}
|
||||
} else if (objComb->unk_1B0 < 0) {
|
||||
objComb->unk_1B0 = 0;
|
||||
}
|
||||
|
||||
if ((objComb->collider.base.acFlags & AC_HIT) != 0) {
|
||||
objComb->collider.base.acFlags &= ~AC_HIT;
|
||||
dmgFlags = objComb->collider.elements[0].info.acHitInfo->toucher.dmgFlags;
|
||||
if (dmgFlags & 0x4001F866) {
|
||||
objComb->unk_1B0 = 1500;
|
||||
} else {
|
||||
ObjComb_Break(objComb, play);
|
||||
ObjComb_RandomizerChooseItemDrop(objComb, play);
|
||||
Actor_Kill(&objComb->actor);
|
||||
}
|
||||
} else {
|
||||
CollisionCheck_SetAC(play, &play->colChkCtx, &objComb->collider.base);
|
||||
}
|
||||
|
||||
if (objComb->actor.update != NULL) {
|
||||
CollisionCheck_SetOC(play, &play->colChkCtx, &objComb->collider.base);
|
||||
}
|
||||
}
|
||||
|
||||
void RandomizerOnActorInitHandler(void* actorRef) {
|
||||
Actor* actor = static_cast<Actor*>(actorRef);
|
||||
|
||||
|
@ -1983,14 +1947,6 @@ void RandomizerOnActorInitHandler(void* actorRef) {
|
|||
}
|
||||
}
|
||||
|
||||
if (actor->id == ACTOR_OBJ_COMB) {
|
||||
ObjComb* objComb = static_cast<ObjComb*>(actorRef);
|
||||
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
|
||||
objComb->beehiveIdentity = OTRGlobals::Instance->gRandomizer->IdentifyBeehive(
|
||||
gPlayState->sceneNum, (s16)actor->world.pos.x, respawnData);
|
||||
objComb->actionFunc = (ObjCombActionFunc)ObjComb_RandomizerWait;
|
||||
}
|
||||
|
||||
if (actor->id == ACTOR_EN_EX_ITEM) {
|
||||
EnExItem* enExItem = static_cast<EnExItem*>(actorRef);
|
||||
|
||||
|
@ -2199,13 +2155,6 @@ void RandomizerOnActorUpdateHandler(void* refActor) {
|
|||
actor->params == 0x000F) { // Warp Song particles
|
||||
Entrance_SetWarpSongEntrance();
|
||||
}
|
||||
|
||||
if (actor->id == ACTOR_OBJ_COMB) {
|
||||
ObjComb* combActor = reinterpret_cast<ObjComb*>(actor);
|
||||
combActor->actor.shape.rot.x =
|
||||
static_cast<int16_t>(Math_SinS(combActor->unk_1B2)) * CLAMP_MIN(combActor->unk_1B0, 0) +
|
||||
combActor->actor.home.rot.x;
|
||||
}
|
||||
}
|
||||
|
||||
// from z_player.c
|
||||
|
|
|
@ -379,9 +379,6 @@ void RegionTable_Init() {
|
|||
areaTable[RR_ROOT] = Region("Root", "", {RA_LINKS_POCKET}, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&logic->KakarikoVillageGateOpen, []{return ctx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN);}),
|
||||
//The big poes bottle softlock safety check does not account for the guard house lock if the guard house is not shuffled, so the key is needed before we can safely allow bottle use in logic
|
||||
//RANDOTODO a setting that lets you drink/dump big poes so we don't need this logic
|
||||
EventAccess(&logic->CouldEmptyBigPoes, []{return !ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) || logic->CanOpenOverworldDoor(RG_GUARD_HOUSE_KEY);}),
|
||||
}, {
|
||||
//Locations
|
||||
LOCATION(RC_LINKS_POCKET, true),
|
||||
|
|
|
@ -54,7 +54,7 @@ void RegionTable_Init_Market() {
|
|||
EventAccess(&logic->CanEmptyBigPoes, []{return logic->IsAdult;}),
|
||||
}, {
|
||||
//Locations
|
||||
LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->BigPoeKill || logic->BigPoes > ctx->GetOption(RSK_BIG_POE_COUNT).Get())),
|
||||
LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->BigPoeKill || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())),
|
||||
LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild),
|
||||
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_1, logic->IsChild && logic->CanBreakPots()),
|
||||
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_2, logic->IsChild && logic->CanBreakPots()),
|
||||
|
|
|
@ -842,40 +842,6 @@ void Rando::StaticData::InitLocationTable() {
|
|||
locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Base(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_HYRULE_FIELD, 0x00, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_TIME), true);
|
||||
locationTable[RC_SONG_FROM_WINDMILL] = Location::Base(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 0x00, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS), true);
|
||||
|
||||
//Beehives
|
||||
locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x2C), "Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_LEFT));
|
||||
locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x2C), "Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_RIGHT));
|
||||
locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x14), "Tunnel Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_LEFT));
|
||||
locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x14), "Tunnel Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_RIGHT));
|
||||
locationTable[RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(747, 0xF5), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_DEKU_SCRUB_GROTTO));
|
||||
locationTable[RC_SFM_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_SFM_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_SACRED_FOREST_MEADOW, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEE), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_SFM_STORMS_GROTTO));
|
||||
locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x00), "Near Market Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_LEFT));
|
||||
locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x00), "Near Market Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_RIGHT));
|
||||
locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x03), "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_LEFT));
|
||||
locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x03), "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_RIGHT));
|
||||
locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x22), "Southeast Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_LEFT));
|
||||
locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x22), "Southeast Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_RIGHT));
|
||||
locationTable[RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE] = Location::Base(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1410, 0xE6), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_LONELY_SCRUB_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_INSIDE_FENCE_GROTTO));
|
||||
locationTable[RC_LLR_GROTTO_BEEHIVE] = Location::Base(RC_LLR_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LON_LON_RANCH, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFC), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LLR_GROTTO));
|
||||
locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x28), "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_LEFT));
|
||||
locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x28), "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_RIGHT));
|
||||
locationTable[RC_DMT_COW_GROTTO_BEEHIVE] = Location::Base(RC_DMT_COW_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2617, 0xF8), "Cow Grotto Beehive", RHT_BEEHIVE_COW_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_COW_GROTTO));
|
||||
locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x57), "Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_LEFT));
|
||||
locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x57), "Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_RIGHT));
|
||||
locationTable[RC_GC_GROTTO_BEEHIVE] = Location::Base(RC_GC_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GORON_CITY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFB), "Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GC_GROTTO));
|
||||
locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x7A), "Upper Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_LEFT));
|
||||
locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x7A), "Upper Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_RIGHT));
|
||||
locationTable[RC_DMC_HAMMER_GROTTO_BEEHIVE] = Location::Base(RC_DMC_HAMMER_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xF9), "Hammer Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_HAMMER_GROTTO));
|
||||
locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x29), "Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_LEFT));
|
||||
locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x29), "Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_RIGHT));
|
||||
locationTable[RC_ZR_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_ZR_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEB), "Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_STORMS_GROTTO));
|
||||
locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(382, 0x00), "In Front of King Zora Beehive Left", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_LEFT));
|
||||
locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(948, 0x00), "In Front of King Zora Beehive Right", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_RIGHT));
|
||||
locationTable[RC_ZD_BEHIND_KING_ZORA_BEEHIVE] = Location::Base(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(701, 0x00), "Behind King Zora Beehive", RHT_BEEHIVE_BEHIND_KING_ZORA, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_BEHIND_KING_ZORA));
|
||||
locationTable[RC_LH_GROTTO_BEEHIVE] = Location::Base(RC_LH_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LAKE_HYLIA, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xEF), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LH_GROTTO));
|
||||
locationTable[RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GERUDO_VALLEY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xF0), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GV_DEKU_SCRUB_GROTTO));
|
||||
locationTable[RC_COLOSSUS_GROTTO_BEEHIVE] = Location::Base(RC_COLOSSUS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DESERT_COLOSSUS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xFD), "Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_COLOSSUS_GROTTO));
|
||||
|
||||
/*-------------------------------
|
||||
--- SHOPS ---
|
||||
8 6 2 4
|
||||
|
|
|
@ -1011,26 +1011,24 @@ Logic::Logic() {
|
|||
|
||||
uint8_t Logic::BottleCount() {
|
||||
uint8_t count = 0;
|
||||
if (CouldEmptyBigPoes && !AreCheckingBigPoes) {
|
||||
for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_4; i++) {
|
||||
uint8_t item = GetSaveContext()->inventory.items[i];
|
||||
switch (item) {
|
||||
case ITEM_LETTER_RUTO:
|
||||
if (DeliverLetter) {
|
||||
count++;
|
||||
}
|
||||
break;
|
||||
case ITEM_BIG_POE:
|
||||
if (CanEmptyBigPoes) {
|
||||
count++;
|
||||
}
|
||||
break;
|
||||
case ITEM_NONE:
|
||||
break;
|
||||
default:
|
||||
for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_4; i++) {
|
||||
uint8_t item = GetSaveContext()->inventory.items[i];
|
||||
switch (item) {
|
||||
case ITEM_LETTER_RUTO:
|
||||
if (DeliverLetter) {
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ITEM_BIG_POE:
|
||||
if (CanEmptyBigPoes) {
|
||||
count++;
|
||||
}
|
||||
break;
|
||||
case ITEM_NONE:
|
||||
break;
|
||||
default:
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
@ -2407,7 +2405,6 @@ void Logic::Reset() {
|
|||
Bottles = 0;
|
||||
NumBottles = 0;
|
||||
CanEmptyBigPoes = false;
|
||||
CouldEmptyBigPoes = false;
|
||||
|
||||
// Drops and Bottle Contents Access
|
||||
NutPot = false;
|
||||
|
|
|
@ -66,12 +66,6 @@ class Logic {
|
|||
uint8_t NumBottles = 0;
|
||||
// this event covers if the player can currently empty big poes in logic
|
||||
bool CanEmptyBigPoes = false;
|
||||
// this event covers if the player could, if they filled their bottle with big poes in field, empty them at the poe
|
||||
// merchant. Works in tandem with the big poes safety check during entrance validation
|
||||
bool CouldEmptyBigPoes = false;
|
||||
// this check is used to tell logic that we are checking big poes accessibility in logic, to ensure it's not
|
||||
// bottle-locked.
|
||||
bool AreCheckingBigPoes = false;
|
||||
|
||||
// Drops and Bottle Contents Access
|
||||
bool NutPot = false;
|
||||
|
|
|
@ -334,7 +334,7 @@ extern "C" void Randomizer_InitSaveFile() {
|
|||
Flags_SetRandomizerInf(RAND_INF_TOT_MASTER_SWORD);
|
||||
}
|
||||
|
||||
HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * (Randomizer_GetSettingValue(RSK_BIG_POE_COUNT) + 1));
|
||||
HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT));
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_SKIP_EPONA_RACE)) {
|
||||
Flags_SetEventChkInf(EVENTCHKINF_EPONA_OBTAINED);
|
||||
|
|
|
@ -268,7 +268,7 @@ void Settings::CreateOptions() {
|
|||
OPT_BOOL(RSK_SKIP_CHILD_ZELDA, "Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
|
||||
OPT_BOOL(RSK_SKIP_EPONA_RACE, "Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
|
||||
OPT_BOOL(RSK_SKIP_SCARECROWS_SONG, "Skip Scarecrow's Song", CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]);
|
||||
OPT_U8(RSK_BIG_POE_COUNT, "Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9);
|
||||
OPT_U8(RSK_BIG_POE_COUNT, "Big Poe Target Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 10);
|
||||
OPT_U8(RSK_CUCCO_COUNT, "Cuccos to return", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("CuccosToReturn"), mOptionDescriptions[RSK_CUCCO_COUNT], WidgetType::Slider, 7);
|
||||
OPT_BOOL(RSK_COMPLETE_MASK_QUEST, "Complete Mask Quest", CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_COMPLETE_MASK_QUEST]);
|
||||
OPT_U8(RSK_GOSSIP_STONE_HINTS, "Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GossipStoneHints"), mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WidgetType::Combobox, RO_GOSSIP_STONES_NEED_NOTHING, false, IMFLAG_NONE);
|
||||
|
|
|
@ -49,6 +49,7 @@ class StaticData {
|
|||
static std::vector<RandomizerCheck> GetPondFishLocations();
|
||||
static std::vector<RandomizerCheck> GetOverworldFishLocations();
|
||||
static std::vector<RandomizerCheck> GetOverworldFairyLocations();
|
||||
static void RegisterBeehiveLocations();
|
||||
static void RegisterCowLocations();
|
||||
static void RegisterFishLocations();
|
||||
static void RegisterFairyLocations();
|
||||
|
|
|
@ -275,7 +275,7 @@ OTRGlobals::OTRGlobals() {
|
|||
if (std::filesystem::exists(ootPath)) {
|
||||
OTRFiles.push_back(ootPath);
|
||||
}
|
||||
std::string sohOtrPath = Ship::Context::GetPathRelativeToAppBundle("soh.otr");
|
||||
std::string sohOtrPath = Ship::Context::LocateFileAcrossAppDirs("soh.otr");
|
||||
if (std::filesystem::exists(sohOtrPath)) {
|
||||
OTRFiles.push_back(sohOtrPath);
|
||||
}
|
||||
|
@ -341,6 +341,10 @@ OTRGlobals::OTRGlobals() {
|
|||
context->InitCrashHandler();
|
||||
context->InitConsole();
|
||||
|
||||
Ship::Context::GetInstance()->GetLogger()->set_level(
|
||||
(spdlog::level::level_enum)CVarGetInteger(CVAR_DEVELOPER_TOOLS("LogLevel"), 1));
|
||||
Ship::Context::GetInstance()->GetLogger()->set_pattern("[%H:%M:%S.%e] [%s:%#] [%l] %v");
|
||||
|
||||
auto sohInputEditorWindow =
|
||||
std::make_shared<SohInputEditorWindow>(CVAR_WINDOW("ControllerConfiguration"), "Configure Controller");
|
||||
auto sohFast3dWindow =
|
||||
|
@ -1167,7 +1171,7 @@ extern "C" void InitOTR() {
|
|||
CheckAndCreateModFolder();
|
||||
#endif
|
||||
|
||||
CheckSoHOTRVersion(Ship::Context::GetPathRelativeToAppBundle("soh.otr"));
|
||||
CheckSoHOTRVersion(Ship::Context::LocateFileAcrossAppDirs("soh.otr"));
|
||||
|
||||
if (!std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName)) &&
|
||||
!std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot.otr", appShortName))) {
|
||||
|
@ -2456,6 +2460,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
|||
CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT);
|
||||
} else if (textId == TEXT_MASK_SHOP_SIGN && ctx->GetOption(RSK_MASK_SHOP_HINT)) {
|
||||
messageEntry = ctx->GetHint(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT);
|
||||
} else if (textId == TEXT_BIG_POE_COLLECTED_RANDO) {
|
||||
messageEntry =
|
||||
CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT);
|
||||
}
|
||||
}
|
||||
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
|
||||
|
|
|
@ -135,6 +135,16 @@ static const std::unordered_map<int32_t, const char*> bonkDamageValues = {
|
|||
{ BONK_DAMAGE_8_HEARTS, "8 Hearts" }, { BONK_DAMAGE_OHKO, "OHKO" },
|
||||
};
|
||||
|
||||
static const std::unordered_map<int32_t, const char*> dampeDropRates = {
|
||||
{ DAMPE_NONE, "None" },
|
||||
{ DAMPE_NORMAL, "Vanilla" },
|
||||
{ DAMPE_JALAPENO, "Jalapeño" },
|
||||
{ DAMPE_CHIPOTLE, "Serrano" },
|
||||
{ DAMPE_SCOTCH_BONNET, "Habanero" },
|
||||
{ DAMPE_GHOST_PEPPER, "Ghost Pepper" },
|
||||
{ DAMPE_INFERNO, "Dampe's Inferno" },
|
||||
};
|
||||
|
||||
static const std::unordered_map<int32_t, const char*> cursorAnywhereValues = {
|
||||
{ PAUSE_ANY_CURSOR_RANDO_ONLY, "Only in Rando" },
|
||||
{ PAUSE_ANY_CURSOR_ALWAYS_ON, "Always" },
|
||||
|
|
|
@ -87,6 +87,17 @@ void SohMenu::AddMenuDevTools() {
|
|||
}
|
||||
})
|
||||
.SameLine(true);
|
||||
AddWidget(path, "Log Level", WIDGET_CVAR_COMBOBOX)
|
||||
.CVar(CVAR_DEVELOPER_TOOLS("LogLevel"))
|
||||
.Options(ComboboxOptions()
|
||||
.Tooltip("The log level determines which messages are printed to the console."
|
||||
" This does not affect the log file output")
|
||||
.ComboMap(logLevels))
|
||||
.Callback([](WidgetInfo& info) {
|
||||
Ship::Context::GetInstance()->GetLogger()->set_level(
|
||||
(spdlog::level::level_enum)CVarGetInteger(CVAR_DEVELOPER_TOOLS("LogLevel"), DEBUG_LOG_DEBUG));
|
||||
})
|
||||
.PreFunc([](WidgetInfo& info) { info.isHidden = mSohMenu->disabledMap.at(DISABLE_FOR_DEBUG_MODE_OFF).active; });
|
||||
|
||||
// Stats
|
||||
path.sidebarName = "Stats";
|
||||
|
|
|
@ -1150,6 +1150,12 @@ void SohMenu::AddMenuEnhancements() {
|
|||
.CVar(CVAR_ENHANCEMENT("TreesDropSticks"))
|
||||
.Options(CheckboxOptions().Tooltip(
|
||||
"Bonking into Trees will have a chance to drop up to 3 Sticks. Must have obtained sticks previously."));
|
||||
AddWidget(path, "Dampe Drop Rate", WIDGET_CVAR_COMBOBOX)
|
||||
.CVar(CVAR_ENHANCEMENT("DampeDropRate"))
|
||||
.Options(ComboboxOptions()
|
||||
.ComboMap(dampeDropRates)
|
||||
.DefaultIndex(DAMPE_NORMAL)
|
||||
.Tooltip("Adjusts rate Dampe drops flames during race."));
|
||||
|
||||
AddWidget(path, "Miscellaneous", WIDGET_SEPARATOR_TEXT);
|
||||
AddWidget(path, "Delete File on Death", WIDGET_CVAR_CHECKBOX)
|
||||
|
@ -1615,6 +1621,9 @@ void SohMenu::AddMenuEnhancements() {
|
|||
.Options(CheckboxOptions().Tooltip(
|
||||
"Keese and Guay no longer target you and simply ignore you as if you were wearing the "
|
||||
"Skull Mask."));
|
||||
AddWidget(path, "No Dampe Fire", WIDGET_CVAR_CHECKBOX)
|
||||
.CVar(CVAR_CHEAT("NoDampeFire"))
|
||||
.Options(CheckboxOptions().Tooltip("Dampe won't drop fireballs during race."));
|
||||
|
||||
AddWidget(path, "Glitch Aids", WIDGET_SEPARATOR_TEXT);
|
||||
AddWidget(path, "Easy Frame Advancing with Pause", WIDGET_CVAR_CHECKBOX)
|
||||
|
|
|
@ -172,4 +172,7 @@ extern "C" void OTRMessage_Init() {
|
|||
CustomMessage("I'm sorry I can't sell you these fine specimens, they need an #experienced owner#.^"
|
||||
"Come back when you have had #Bombchus# of your own.",
|
||||
{ QM_RED, QM_GREEN }));
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
customMessageTableID, TEXT_BIG_POE_COLLECTED_RANDO,
|
||||
CustomMessage("You have #" + CustomMessage::POINTS("\x01") + "# points.", { QM_RED }));
|
||||
}
|
||||
|
|
|
@ -288,19 +288,21 @@ void func_80A2F83C(EnGb* this, PlayState* play) {
|
|||
}
|
||||
}
|
||||
if (Actor_ProcessTalkRequest(&this->dyna.actor, play)) {
|
||||
switch (func_8002F368(play)) {
|
||||
case EXCH_ITEM_NONE:
|
||||
func_80A2F180(this);
|
||||
this->actionFunc = func_80A2F94C;
|
||||
break;
|
||||
case EXCH_ITEM_POE:
|
||||
player->actor.textId = 0x70F6;
|
||||
this->actionFunc = func_80A2F9C0;
|
||||
break;
|
||||
case EXCH_ITEM_BIG_POE:
|
||||
player->actor.textId = 0x70F7;
|
||||
this->actionFunc = func_80A2FA50;
|
||||
break;
|
||||
if (GameInteractor_Should(VB_SELL_POES_TO_POE_COLLECTOR, true, this)) {
|
||||
switch (func_8002F368(play)) {
|
||||
case EXCH_ITEM_NONE:
|
||||
func_80A2F180(this);
|
||||
this->actionFunc = func_80A2F94C;
|
||||
break;
|
||||
case EXCH_ITEM_POE:
|
||||
player->actor.textId = 0x70F6;
|
||||
this->actionFunc = func_80A2F9C0;
|
||||
break;
|
||||
case EXCH_ITEM_BIG_POE:
|
||||
player->actor.textId = 0x70F7;
|
||||
this->actionFunc = func_80A2FA50;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef struct EnGb {
|
|||
/* 0x0388 */ EnGbCagedSoul cagedSouls[4];
|
||||
} EnGb; // size = 0x0438
|
||||
|
||||
void func_80A2FC0C(EnGb* actor, PlayState* play);
|
||||
void func_80A2FB40(EnGb* actor, PlayState* play);
|
||||
void func_80A2F83C(EnGb* actor, PlayState* play);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -712,7 +712,7 @@ void EnPoField_SoulInteract(EnPoField* this, PlayState* play) {
|
|||
if (this->actor.params == 0) {
|
||||
Item_Give(play, ITEM_POE);
|
||||
this->actor.textId = 0x5008;
|
||||
} else {
|
||||
} else if (GameInteractor_Should(VB_BOTTLE_BIG_POE, true, this)) {
|
||||
this->actor.textId = 0x508F;
|
||||
Item_Give(play, ITEM_BIG_POE);
|
||||
Flags_SetSwitch(play, sEnPoFieldSpawnSwitchFlags[this->spawnFlagIndex]);
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "overlays/actors/ovl_En_Honotrap/z_en_honotrap.h"
|
||||
#include "objects/object_tk/object_tk.h"
|
||||
#include "soh/ResourceManagerHelpers.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
|
||||
#define FLAGS \
|
||||
(ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \
|
||||
|
@ -197,7 +199,7 @@ void EnPoRelay_Race(EnPoRelay* this, PlayState* play) {
|
|||
if (this->actionTimer != 0) {
|
||||
this->actionTimer--;
|
||||
}
|
||||
if (this->actionTimer == 0 && Rand_ZeroOne() < 0.03f) {
|
||||
if (GameInteractor_Should(VB_DAMPE_DROP_FLAME, this->actionTimer == 0 && Rand_ZeroOne() < 0.03f, this)) {
|
||||
this->actionTimer = 32;
|
||||
if (this->pathIndex < 23) {
|
||||
speed = Rand_ZeroOne() * 3.0f;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue