Merge branch 'develop' into SplitGF

This commit is contained in:
Pepper0ni 2025-05-23 22:58:36 +01:00
commit 997ac266bc
90 changed files with 788 additions and 413 deletions

View file

@ -39,7 +39,7 @@ $files = Get-ChildItem -Path $basePath\soh -Recurse -File `
| Where-Object { ($_.Extension -eq '.c' -or $_.Extension -eq '.cpp' -or `
(($_.Extension -eq '.h' -or $_.Extension -eq '.hpp') -and `
(-not ($_.FullName -like "*\soh\src\*" -or $_.FullName -like "*\soh\include\*")))) -and `
(-not ($_.FullName -like "*\soh\assets\*")) }
(-not ($_.FullName -like "*\soh\assets\*" -or $_.FullName -like "*\soh\build\*")) }
for ($i = 0; $i -lt $files.Length; $i++) {
$file = $files[$i]

View 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") });

View 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 });

View file

@ -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),

View 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 });

View file

@ -77,9 +77,9 @@ void CrawlSpeed_Register() {
COND_VB_SHOULD(VB_CRAWL_SPEED_EXIT_CS, shouldRegister, {
Player* player = GET_PLAYER(gPlayState);
Camera* csCam = va_arg(args, Camera*);
s16 csId = va_arg(args, s16);
s16 actionParameters = va_arg(args, s16);
s16 initTimer = va_arg(args, s16);
s16 csId = static_cast<s16>(va_arg(args, int));
s16 actionParameters = static_cast<s16>(va_arg(args, int));
s16 initTimer = static_cast<s16>(va_arg(args, int));
CutsceneCameraPoint* atPoints = va_arg(args, CutsceneCameraPoint*);
CutsceneCameraPoint* eyePoints = va_arg(args, CutsceneCameraPoint*);
bool excludeWellBackroom = (player->actor.world.pos.x > 950.0f) && (player->actor.world.pos.x < 1025.0f) &&

View file

@ -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,

View file

@ -17,6 +17,7 @@
#include <spdlog/fmt/fmt.h>
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
#include "soh/ObjectExtension/ActorListIndex.h"
extern "C" {
#include <z64.h>
@ -998,6 +999,7 @@ void ActorViewerWindow::DrawElement() {
ImGui::Text("Category: %s", acMapping[display->category]);
ImGui::Text("ID: %d", display->id);
ImGui::Text("Parameters: %d", display->params);
ImGui::Text("Actor List Index: %d", GetActorListIndex(display));
},
"Selected Actor");
ImGui::SameLine();

View file

@ -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,

View file

@ -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

View file

@ -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();

View file

@ -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();
}

View file

@ -72,4 +72,4 @@ void GeneratePlaythrough();
bool CheckBeatable(RandomizerGet ignore = RG_NONE);
void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAccess);
void ValidateEntrances(bool checkOtherEntranceAccess);

View file

@ -40,7 +40,7 @@ const CustomMessage& HintText::GetObscure() const {
return obscureText.size() > 0 ? RandomElement(obscureText) : clearText;
}
const CustomMessage& HintText::GetObscure(uint8_t selection) const {
const CustomMessage& HintText::GetObscure(size_t selection) const {
if (obscureText.size() > selection) {
return obscureText[selection];
} else if (obscureText.size() > 0) {
@ -53,7 +53,7 @@ const CustomMessage& HintText::GetAmbiguous() const {
return ambiguousText.size() > 0 ? RandomElement(ambiguousText) : clearText;
}
const CustomMessage& HintText::GetAmbiguous(uint8_t selection) const {
const CustomMessage& HintText::GetAmbiguous(size_t selection) const {
if (ambiguousText.size() > selection) {
return ambiguousText[selection];
} else if (ambiguousText.size() > 0) {
@ -62,15 +62,15 @@ const CustomMessage& HintText::GetAmbiguous(uint8_t selection) const {
return clearText;
}
uint8_t HintText::GetAmbiguousSize() const {
return static_cast<uint8_t>(ambiguousText.size());
size_t HintText::GetAmbiguousSize() const {
return ambiguousText.size();
}
uint8_t HintText::GetObscureSize() const {
return static_cast<uint8_t>(obscureText.size());
size_t HintText::GetObscureSize() const {
return obscureText.size();
}
const CustomMessage& HintText::GetHintMessage(uint8_t selection) const {
const CustomMessage& HintText::GetHintMessage(size_t selection) const {
auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)) {
return GetObscure(selection);
@ -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();

View file

@ -37,12 +37,12 @@ class HintText {
std::vector<CustomMessage> obscureText_ = {});
const CustomMessage& GetClear() const;
const CustomMessage& GetObscure() const;
const CustomMessage& GetObscure(uint8_t selection) const;
const CustomMessage& GetObscure(size_t selection) const;
const CustomMessage& GetAmbiguous() const;
const CustomMessage& GetAmbiguous(uint8_t selection) const;
uint8_t GetAmbiguousSize() const;
uint8_t GetObscureSize() const;
const CustomMessage& GetHintMessage(uint8_t selection = 0) const;
const CustomMessage& GetAmbiguous(size_t selection) const;
size_t GetAmbiguousSize() const;
size_t GetObscureSize() const;
const CustomMessage& GetHintMessage(size_t selection = 0) const;
const CustomMessage GetMessageCopy() const;
bool operator==(const HintText& right) const;
bool operator!=(const HintText& right) const;

View 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);

View file

@ -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
}

View file

@ -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) &&

View file

@ -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;
}

View file

@ -174,8 +174,8 @@ void Hint::NamesChosen() {
auto ctx = Rando::Context::GetInstance();
std::vector<uint8_t> namesTemp = {};
bool saveNames = false;
uint8_t numMessages = GetNumberOfMessages();
for (uint8_t c = 0; c < numMessages; c++) {
size_t numMessages = GetNumberOfMessages();
for (size_t c = 0; c < numMessages; c++) {
uint8_t selection = GetRandomHintTextEntry(GetHintText(c));
if (selection > 0) {
saveNames = true;
@ -187,7 +187,7 @@ void Hint::NamesChosen() {
}
if (hintType == HINT_TYPE_ITEM || hintType == HINT_TYPE_ITEM_AREA) {
for (uint8_t c = 0; c < locations.size(); c++) {
for (size_t c = 0; c < locations.size(); c++) {
namesTemp = {};
saveNames = false;
uint8_t selection = GetRandomHintTextEntry(GetItemHintText(c));
@ -218,7 +218,7 @@ void Hint::NamesChosen() {
}
}
uint8_t Hint::GetNumberOfMessages() const {
size_t Hint::GetNumberOfMessages() const {
size_t numMessages = std::max(messages.size(), hintKeys.size());
if (StaticData::staticHintInfoMap.contains(ownKey)) {
numMessages = std::max(StaticData::staticHintInfoMap[ownKey].hintKeys.size(), numMessages);
@ -226,20 +226,19 @@ uint8_t Hint::GetNumberOfMessages() const {
if (numMessages == 0) {
numMessages = 1; // RANDOTODO make std::max actually fucking work for 3 arguments
}
// RANDOTODO will number of messages always be u8?
return static_cast<uint8_t>(numMessages);
return numMessages;
}
const std::vector<std::string> Hint::GetAllMessageStrings(MessageFormat format) const {
std::vector<std::string> hintMessages = {};
uint8_t numMessages = GetNumberOfMessages();
for (int c = 0; c < numMessages; c++) {
size_t numMessages = GetNumberOfMessages();
for (size_t c = 0; c < numMessages; c++) {
hintMessages.push_back(GetHintMessage(format, c).GetForCurrentLanguage(format));
}
return hintMessages;
}
const HintText Hint::GetHintText(uint8_t id) const {
const HintText Hint::GetHintText(size_t id) const {
auto ctx = Rando::Context::GetInstance();
if (hintKeys.size() > id) {
return StaticData::hintTextTable[hintKeys[id]];
@ -284,11 +283,11 @@ const HintText Hint::GetHintText(uint8_t id) const {
}
}
const CustomMessage Hint::GetHintMessage(MessageFormat format, uint8_t id) const {
const CustomMessage Hint::GetHintMessage(MessageFormat format, size_t id) const {
auto ctx = Rando::Context::GetInstance();
CustomMessage hintText = CustomMessage("");
uint8_t chosenMessage = 0;
size_t chosenMessage = 0;
if (hintTextsChosen.size() > id) {
chosenMessage = id;
}

View file

@ -23,10 +23,10 @@ class Hint {
void FillGapsInData();
void SetLocationsAsHinted() const;
void NamesChosen();
uint8_t GetNumberOfMessages() const;
size_t GetNumberOfMessages() const;
const std::vector<std::string> GetAllMessageStrings(MessageFormat format = MF_AUTO_FORMAT) const;
const CustomMessage GetHintMessage(MessageFormat format = MF_AUTO_FORMAT, uint8_t id = 0) const;
const HintText GetHintText(uint8_t id = 0) const;
const CustomMessage GetHintMessage(MessageFormat format = MF_AUTO_FORMAT, size_t id = 0) const;
const HintText GetHintText(size_t id = 0) const;
oJson toJSON();
void logHint(oJson& jsonData);
const HintText GetItemHintText(uint8_t slot, bool mysterious = false) const;

View file

@ -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

View file

@ -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);}),
EventAccess(&logic->THCouldFree1TorchCarpenter, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE);}),
EventAccess(&logic->THCouldFreeDoubleCellCarpenter, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}),
EventAccess(&logic->TH_CouldFreeDeadEndCarpenter, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FAST);}),

View file

@ -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()),

View file

@ -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

View file

@ -1020,26 +1020,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;
@ -2406,7 +2404,6 @@ void Logic::Reset() {
Bottles = 0;
NumBottles = 0;
CanEmptyBigPoes = false;
CouldEmptyBigPoes = false;
// Drops and Bottle Contents Access
NutPot = false;

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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();

View file

@ -272,7 +272,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);
}
@ -332,6 +332,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 =
@ -1153,7 +1157,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))) {
@ -2436,6 +2440,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) {

View file

@ -0,0 +1,16 @@
#include "ActorListIndex.h"
#include "soh/ObjectExtension/ObjectExtension.h"
struct ActorListIndex {
s16 index = -1;
};
static ObjectExtension::Register<ActorListIndex> ActorListIndexRegister;
int16_t GetActorListIndex(const Actor* actor) {
const ActorListIndex* index = ObjectExtension::GetInstance().Get<ActorListIndex>(actor);
return index != nullptr ? index->index : ActorListIndex{}.index;
}
void SetActorListIndex(const Actor* actor, int16_t index) {
ObjectExtension::GetInstance().Set<ActorListIndex>(actor, ActorListIndex{ index });
}

View file

@ -0,0 +1,16 @@
#ifndef ACTOR_LIST_INDEX_H
#define ACTOR_LIST_INDEX_H
#ifdef __cplusplus
extern "C" {
#include "z64actor.h"
#endif
int16_t GetActorListIndex(const Actor* actor);
void SetActorListIndex(const Actor* actor, int16_t index);
#ifdef __cplusplus
}
#endif
#endif // ACTOR_LIST_INDEX_H

View file

@ -0,0 +1,25 @@
#include "ObjectExtension.h"
ObjectExtension& ObjectExtension::GetInstance() {
static ObjectExtension instance;
return instance;
}
ObjectExtension::Id ObjectExtension::RegisterId() {
return NextId++;
}
void ObjectExtension::Free(const void* object) {
if (object == nullptr) {
return;
}
std::erase_if(Data, [&object](const auto& iter) {
auto const& [key, value] = iter;
return key.first == object;
});
}
extern "C" void ObjectExtension_Free(const void* object) {
ObjectExtension::GetInstance().Free(object);
}

View file

@ -0,0 +1,116 @@
#pragma once
#ifdef __cplusplus
#include <libultraship/libultraship.h>
#include <any>
#include <limits>
#include <stdint.h>
#include <unordered_map>
#include <vector>
/*
* This class can attach additional data to pointers. It can only attach a single instance of each type of data.
* Use the ObjectExtension::Register class to register a type to be used as an object extension.
* An example usage is:
*
* struct MyData {
* s32 data = -1;
* };
* static ObjectExtension::Register<MyData> MyDataRegister;
*
* Then you can get with
* ObjectExtension::GetInstance().Get<MyData>(ptr);
* and set with
* ObjectExtension::GetInstance().Set<MyData>(ptr, MyData{});
* (or with the returned pointer from Get()).
*/
class ObjectExtension {
public:
using Id = uint32_t;
static constexpr Id InvalidId = std::numeric_limits<Id>::max();
// Registers type T to be used as an object extension
template <typename T> class Register {
public:
Register() {
Id = ObjectExtension::GetInstance().RegisterId();
}
static ObjectExtension::Id Id;
};
// Gets the singleton ObjectExtension instance
static ObjectExtension& GetInstance();
// Gets the data of type T associated with an object, or nullptr if no such data has been attached
template <typename T> T* Get(const void* object) {
assert(ObjectExtension::Register<T>::Id != InvalidId);
if (object == nullptr) {
return nullptr;
}
auto it = Data.find(std::make_pair(object, ObjectExtension::Register<T>::Id));
if (it == Data.end()) {
return nullptr;
}
return std::any_cast<T>(&(it->second));
}
// Sets the data of type T for an object. Data will be copied.
template <typename T> void Set(const void* object, const T&& data) {
assert(ObjectExtension::Register<T>::Id != InvalidId);
if (object != nullptr) {
Data[std::make_pair(object, ObjectExtension::Register<T>::Id)] = data;
}
}
// Returns true if an object has data of type T associated with it
template <typename T> bool Has(const void* object) {
assert(ObjectExtension::Register<T>::Id != InvalidId);
if (object == nullptr) {
return false;
}
return Data.contains(std::make_pair(object, ObjectExtension::Register<T>::Id));
}
// Removes data of type T from an object
template <typename T> void Remove(const void* object) {
assert(ObjectExtension::Register<T>::Id != InvalidId);
Data.erase(std::make_pair(object, ObjectExtension::Register<T>::Id));
}
// Removes all data from an object
void Free(const void* object);
private:
ObjectExtension() = default;
// Returns the next free object extension Id
Id RegisterId();
ObjectExtension::Id NextId = 0;
struct KeyHash {
std::size_t operator()(const std::pair<const void*, ObjectExtension::Id>& key) const {
return std::hash<const void*>{}(key.first) ^ (std::hash<ObjectExtension::Id>{}(key.second) << 1);
}
};
// Collection of all object extension data.
std::unordered_map<std::pair<const void*, ObjectExtension::Id>, std::any, KeyHash> Data;
};
// Static template globals
template <typename T> ObjectExtension::Id ObjectExtension::Register<T>::Id = ObjectExtension::InvalidId;
#else // __cplusplus
void ObjectExtension_Free(const void* object);
#endif // __cplusplus

View file

@ -922,6 +922,12 @@ void SaveManager::InitFileDebug() {
gSaveContext.playerName[i] = sPlayerName[i];
}
gSaveContext.ship.filenameLanguage = NAME_LANGUAGE_PAL;
} else if (gSaveContext.language == LANGUAGE_JPN) { // Japanese
const static std::array<char, 8> sPlayerName = { 0x81, 0x87, 0x61, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF };
for (int i = 0; i < ARRAY_COUNT(gSaveContext.playerName); i++) {
gSaveContext.playerName[i] = sPlayerName[i];
}
gSaveContext.ship.filenameLanguage = NAME_LANGUAGE_NTSC_JPN;
} else { // GAME_REGION_NTSC
const static std::array<char, 8> sPlayerName = { 0xB6, 0xB3, 0xB8, 0xB5, 0xDF, 0xDF, 0xDF, 0xDF };
for (int i = 0; i < ARRAY_COUNT(gSaveContext.playerName); i++) {
@ -1037,6 +1043,12 @@ void SaveManager::InitFileMaxed() {
gSaveContext.playerName[i] = sPlayerName[i];
}
gSaveContext.ship.filenameLanguage = NAME_LANGUAGE_PAL;
} else if (gSaveContext.language == LANGUAGE_JPN) { // Japanese
const static std::array<char, 8> sPlayerName = { 0x81, 0x87, 0x61, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF };
for (int i = 0; i < ARRAY_COUNT(gSaveContext.playerName); i++) {
gSaveContext.playerName[i] = sPlayerName[i];
}
gSaveContext.ship.filenameLanguage = NAME_LANGUAGE_NTSC_JPN;
} else { // GAME_REGION_NTSC
const static std::array<char, 8> sPlayerName = { 0xB6, 0xB3, 0xB8, 0xB5, 0xDF, 0xDF, 0xDF, 0xDF };
for (int i = 0; i < ARRAY_COUNT(gSaveContext.playerName); i++) {

View file

@ -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" },

View file

@ -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";

View file

@ -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)

View file

@ -1,19 +1,19 @@
#include "libultraship/libultraship.h"
namespace SOH {
class ConfigVersion1Updater : public Ship::ConfigVersionUpdater {
class ConfigVersion1Updater final : public Ship::ConfigVersionUpdater {
public:
ConfigVersion1Updater();
void Update(Ship::Config* conf);
};
class ConfigVersion2Updater : public Ship::ConfigVersionUpdater {
class ConfigVersion2Updater final : public Ship::ConfigVersionUpdater {
public:
ConfigVersion2Updater();
void Update(Ship::Config* conf);
};
class ConfigVersion3Updater : public Ship::ConfigVersionUpdater {
class ConfigVersion3Updater final : public Ship::ConfigVersionUpdater {
public:
ConfigVersion3Updater();
void Update(Ship::Config* conf);

View file

@ -4,7 +4,7 @@
#include "ResourceFactoryBinary.h"
namespace SOH {
class ResourceFactoryBinaryAnimationV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryAnimationV0 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -4,7 +4,7 @@
#include "resource/ResourceFactoryBinary.h"
namespace SOH {
class ResourceFactoryBinaryArrayV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryArrayV0 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -4,7 +4,7 @@
#include "ResourceFactoryBinary.h"
namespace SOH {
class ResourceFactoryBinaryAudioSampleV2 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryAudioSampleV2 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -15,7 +15,7 @@ ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr<Ship::File> f
audioSequence->sequence.seqDataSize = reader->ReadInt32();
audioSequence->sequenceData.reserve(audioSequence->sequence.seqDataSize);
for (uint32_t i = 0; i < audioSequence->sequence.seqDataSize; i++) {
for (int32_t i = 0; i < audioSequence->sequence.seqDataSize; i++) {
audioSequence->sequenceData.push_back(reader->ReadChar());
}
audioSequence->sequence.seqData = audioSequence->sequenceData.data();
@ -25,10 +25,10 @@ ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr<Ship::File> f
audioSequence->sequence.cachePolicy = reader->ReadUByte();
audioSequence->sequence.numFonts = reader->ReadUInt32();
for (uint32_t i = 0; i < 16; i++) {
for (int32_t i = 0; i < 16; i++) {
audioSequence->sequence.fonts[i] = 0;
}
for (uint32_t i = 0; i < audioSequence->sequence.numFonts; i++) {
for (int32_t i = 0; i < audioSequence->sequence.numFonts; i++) {
audioSequence->sequence.fonts[i] = reader->ReadUByte();
}

View file

@ -4,7 +4,7 @@
#include "ResourceFactoryBinary.h"
namespace SOH {
class ResourceFactoryBinaryAudioSequenceV2 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryAudioSequenceV2 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -4,7 +4,7 @@
#include "ResourceFactoryBinary.h"
namespace SOH {
class ResourceFactoryBinaryAudioSoundFontV2 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryAudioSoundFontV2 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -4,7 +4,7 @@
#include "resource/ResourceFactoryBinary.h"
namespace SOH {
class ResourceFactoryBinaryBackgroundV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryBackgroundV0 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -5,13 +5,13 @@
#include "ResourceFactoryXML.h"
namespace SOH {
class ResourceFactoryBinaryCollisionHeaderV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryCollisionHeaderV0 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;
};
class ResourceFactoryXMLCollisionHeaderV0 : public Ship::ResourceFactoryXML {
class ResourceFactoryXMLCollisionHeaderV0 final : public Ship::ResourceFactoryXML {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -4,7 +4,7 @@
#include "ResourceFactoryBinary.h"
namespace SOH {
class ResourceFactoryBinaryCutsceneV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryCutsceneV0 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -5,13 +5,13 @@
#include "ResourceFactoryXML.h"
namespace SOH {
class ResourceFactoryBinaryPathV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryPathV0 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;
};
class ResourceFactoryXMLPathV0 : public Ship::ResourceFactoryXML {
class ResourceFactoryXMLPathV0 final : public Ship::ResourceFactoryXML {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -4,7 +4,7 @@
#include "ResourceFactoryBinary.h"
namespace SOH {
class ResourceFactoryBinaryPlayerAnimationV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryPlayerAnimationV0 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -8,7 +8,7 @@
#include "ResourceFactoryXML.h"
namespace SOH {
class ResourceFactoryBinarySceneV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinarySceneV0 final : public Ship::ResourceFactoryBinary {
public:
ResourceFactoryBinarySceneV0();
@ -28,7 +28,7 @@ class ResourceFactoryBinarySceneV0 : public Ship::ResourceFactoryBinary {
std::shared_ptr<Ship::BinaryReader> reader, uint32_t index);
};
class ResourceFactoryXMLSceneV0 : public Ship::ResourceFactoryXML {
class ResourceFactoryXMLSceneV0 final : public Ship::ResourceFactoryXML {
public:
ResourceFactoryXMLSceneV0();

View file

@ -23,7 +23,7 @@ ResourceFactoryBinarySkeletonV0::ReadResource(std::shared_ptr<Ship::File> file,
skeleton->limbTableCount = reader->ReadUInt32();
skeleton->limbTable.reserve(skeleton->limbTableCount);
for (uint32_t i = 0; i < skeleton->limbTableCount; i++) {
for (int32_t i = 0; i < skeleton->limbTableCount; i++) {
std::string limbPath = reader->ReadString();
skeleton->limbTable.push_back(limbPath);

View file

@ -5,13 +5,13 @@
#include "ResourceFactoryXML.h"
namespace SOH {
class ResourceFactoryBinarySkeletonV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinarySkeletonV0 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;
};
class ResourceFactoryXMLSkeletonV0 : public Ship::ResourceFactoryXML {
class ResourceFactoryXMLSkeletonV0 final : public Ship::ResourceFactoryXML {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -5,13 +5,13 @@
#include "ResourceFactoryXML.h"
namespace SOH {
class ResourceFactoryBinarySkeletonLimbV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinarySkeletonLimbV0 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;
};
class ResourceFactoryXMLSkeletonLimbV0 : public Ship::ResourceFactoryXML {
class ResourceFactoryXMLSkeletonLimbV0 final : public Ship::ResourceFactoryXML {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -5,13 +5,13 @@
#include "ResourceFactoryXML.h"
namespace SOH {
class ResourceFactoryBinaryTextV0 : public Ship::ResourceFactoryBinary {
class ResourceFactoryBinaryTextV0 final : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;
};
class ResourceFactoryXMLTextV0 : public Ship::ResourceFactoryXML {
class ResourceFactoryXMLTextV0 final : public Ship::ResourceFactoryXML {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
std::shared_ptr<Ship::ResourceInitData> initData) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class EndMarkerFactory : public SceneCommandFactoryBinaryV0 {
class EndMarkerFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class EndMarkerFactoryXML : public SceneCommandFactoryXMLV0 {
class EndMarkerFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetActorListFactory : public SceneCommandFactoryBinaryV0 {
class SetActorListFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetActorListFactoryXML : public SceneCommandFactoryXMLV0 {
class SetActorListFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetAlternateHeadersFactory : public SceneCommandFactoryBinaryV0 {
class SetAlternateHeadersFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetAlternateHeadersFactoryXML : public SceneCommandFactoryXMLV0 {
class SetAlternateHeadersFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetCameraSettingsFactory : public SceneCommandFactoryBinaryV0 {
class SetCameraSettingsFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetCameraSettingsFactoryXML : public SceneCommandFactoryXMLV0 {
class SetCameraSettingsFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetCollisionHeaderFactory : public SceneCommandFactoryBinaryV0 {
class SetCollisionHeaderFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetCollisionHeaderFactoryXML : public SceneCommandFactoryXMLV0 {
class SetCollisionHeaderFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetCsCameraFactory : public SceneCommandFactoryBinaryV0 {
class SetCsCameraFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetCsCameraFactoryXML : public SceneCommandFactoryXMLV0 {
class SetCsCameraFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetCutscenesFactory : public SceneCommandFactoryBinaryV0 {
class SetCutscenesFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetCutscenesFactoryXML : public SceneCommandFactoryXMLV0 {
class SetCutscenesFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetEchoSettingsFactory : public SceneCommandFactoryBinaryV0 {
class SetEchoSettingsFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetEchoSettingsFactoryXML : public SceneCommandFactoryXMLV0 {
class SetEchoSettingsFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetEntranceListFactory : public SceneCommandFactoryBinaryV0 {
class SetEntranceListFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetEntranceListFactoryXML : public SceneCommandFactoryXMLV0 {
class SetEntranceListFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetExitListFactory : public SceneCommandFactoryBinaryV0 {
class SetExitListFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetExitListFactoryXML : public SceneCommandFactoryXMLV0 {
class SetExitListFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetLightListFactory : public SceneCommandFactoryBinaryV0 {
class SetLightListFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetLightListFactoryXML : public SceneCommandFactoryXMLV0 {
class SetLightListFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetLightingSettingsFactory : public SceneCommandFactoryBinaryV0 {
class SetLightingSettingsFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetLightingSettingsFactoryXML : public SceneCommandFactoryXMLV0 {
class SetLightingSettingsFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetMeshFactory : public SceneCommandFactoryBinaryV0 {
class SetMeshFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetMeshFactoryXML : public SceneCommandFactoryXMLV0 {
class SetMeshFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetObjectListFactory : public SceneCommandFactoryBinaryV0 {
class SetObjectListFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetObjectListFactoryXML : public SceneCommandFactoryXMLV0 {
class SetObjectListFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetPathwaysFactory : public SceneCommandFactoryBinaryV0 {
class SetPathwaysFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetPathwaysFactoryXML : public SceneCommandFactoryXMLV0 {
class SetPathwaysFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetRoomBehaviorFactory : public SceneCommandFactoryBinaryV0 {
class SetRoomBehaviorFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetRoomBehaviorFactoryXML : public SceneCommandFactoryXMLV0 {
class SetRoomBehaviorFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetRoomListFactory : public SceneCommandFactoryBinaryV0 {
class SetRoomListFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetRoomListFactoryXML : public SceneCommandFactoryXMLV0 {
class SetRoomListFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetSkyboxModifierFactory : public SceneCommandFactoryBinaryV0 {
class SetSkyboxModifierFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetSkyboxModifierFactoryXML : public SceneCommandFactoryXMLV0 {
class SetSkyboxModifierFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetSkyboxSettingsFactory : public SceneCommandFactoryBinaryV0 {
class SetSkyboxSettingsFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetSkyboxSettingsFactoryXML : public SceneCommandFactoryXMLV0 {
class SetSkyboxSettingsFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetSoundSettingsFactory : public SceneCommandFactoryBinaryV0 {
class SetSoundSettingsFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetSoundSettingsFactoryXML : public SceneCommandFactoryXMLV0 {
class SetSoundSettingsFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetSpecialObjectsFactory : public SceneCommandFactoryBinaryV0 {
class SetSpecialObjectsFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetSpecialObjectsFactoryXML : public SceneCommandFactoryXMLV0 {
class SetSpecialObjectsFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetStartPositionListFactory : public SceneCommandFactoryBinaryV0 {
class SetStartPositionListFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetStartPositionListFactoryXML : public SceneCommandFactoryXMLV0 {
class SetStartPositionListFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetTimeSettingsFactory : public SceneCommandFactoryBinaryV0 {
class SetTimeSettingsFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetTimeSettingsFactoryXML : public SceneCommandFactoryXMLV0 {
class SetTimeSettingsFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetTransitionActorListFactory : public SceneCommandFactoryBinaryV0 {
class SetTransitionActorListFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetTransitionActorListFactoryXML : public SceneCommandFactoryXMLV0 {
class SetTransitionActorListFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -3,13 +3,13 @@
#include "soh/resource/importer/scenecommand/SceneCommandFactory.h"
namespace SOH {
class SetWindSettingsFactory : public SceneCommandFactoryBinaryV0 {
class SetWindSettingsFactory final : public SceneCommandFactoryBinaryV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
std::shared_ptr<Ship::BinaryReader> reader) override;
};
class SetWindSettingsFactoryXML : public SceneCommandFactoryXMLV0 {
class SetWindSettingsFactoryXML final : public SceneCommandFactoryXMLV0 {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::ResourceInitData> initData,
tinyxml2::XMLElement* reader) override;

View file

@ -35,7 +35,7 @@ typedef struct {
/* 0x2 */ LightParams params;
} LightInfo; // size = 0xE
class SetLightList : public SceneCommand<LightInfo> {
class SetLightList final : public SceneCommand<LightInfo> {
public:
using SceneCommand::SceneCommand;

View file

@ -19,7 +19,7 @@ typedef struct {
/* 0x14 */ s16 fogFar;
} EnvLightSettings; // size = 0x16
class SetLightingSettings : public SceneCommand<EnvLightSettings> {
class SetLightingSettings final : public SceneCommand<EnvLightSettings> {
public:
using SceneCommand::SceneCommand;

View file

@ -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 }));
}

View file

@ -7,6 +7,8 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
#include "objects/object_bdoor/object_bdoor.h"
#include "soh/ObjectExtension/ObjectExtension.h"
#include "soh/ObjectExtension/ActorListIndex.h"
#include "soh/frame_interpolation.h"
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
#include "soh/Enhancements/enemyrandomizer.h"
@ -2574,7 +2576,11 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
if (play->numSetupActors != 0) {
actorEntry = &play->setupActorList[0];
for (i = 0; i < play->numSetupActors; i++) {
Actor_SpawnEntry(&play->actorCtx, actorEntry++, play);
Actor* spawnedActor = Actor_SpawnEntry(&play->actorCtx, actorEntry++, play);
// #region SOH [ObjectExtension] ActorListIndex tracking
SetActorListIndex(spawnedActor, (s16)i);
// #endregion
}
play->numSetupActors = 0;
GameInteractor_ExecuteOnSceneSpawnActors();
@ -3352,6 +3358,10 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos
return NULL;
}
// #region SOH [ObjectExtension]
SetActorListIndex(actor, -1);
// #endregion
assert(dbEntry->numLoaded < 255);
dbEntry->numLoaded++;
@ -3497,6 +3507,10 @@ Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) {
newHead = Actor_RemoveFromCategory(play, actorCtx, actor);
// #region SOH [ObjectExtension]
ObjectExtension_Free(actor);
// #endregion
ZELDA_ARENA_FREE_DEBUG(actor);
dbEntry->numLoaded--;

View file

@ -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;
}

View file

@ -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

View file

@ -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]);

View file

@ -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;

View file

@ -1086,10 +1086,6 @@ static s16 sLastFileChooseButtonIndex;
* Update function for `CM_MAIN_MENU`
*/
void FileChoose_UpdateMainMenu(GameState* thisx) {
static u8 emptyName[] = { 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E };
static u8 emptyNameNES[] = { 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF };
static u8 linkName[] = { 0x15, 0x2C, 0x31, 0x2E, 0x3E, 0x3E, 0x3E, 0x3E };
static u8 linkNameNES[] = { 0xB6, 0xB3, 0xB8, 0xB5, 0xDF, 0xDF, 0xDF, 0xDF };
FileChooseContext* this = (FileChooseContext*)thisx;
Input* input = &this->state.input[0];
bool dpad = CVarGetInteger(CVAR_SETTING("DpadInText"), 0);
@ -1300,6 +1296,7 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) {
static u8 emptyNameNES[] = { 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF };
static u8 linkName[] = { 0x15, 0x2C, 0x31, 0x2E, 0x3E, 0x3E, 0x3E, 0x3E };
static u8 linkNameNES[] = { 0xB6, 0xB3, 0xB8, 0xB5, 0xDF, 0xDF, 0xDF, 0xDF };
static u8 linkNameJP[] = { 0x81, 0x87, 0x61, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF };
FileChoose_UpdateStickDirectionPromptAnim(thisx);
FileChooseContext* this = (FileChooseContext*)thisx;
Input* input = &this->state.input[0];
@ -1369,6 +1366,14 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) {
this->nameEntryBoxAlpha = 0;
if (ResourceMgr_GetGameRegion(0) == GAME_REGION_PAL && gSaveContext.language != LANGUAGE_JPN) {
defaultName = CVarGetInteger(CVAR_ENHANCEMENT("LinkDefaultName"), 0) ? &linkName : &emptyName;
} else if (gSaveContext.language == LANGUAGE_JPN) { // Japanese
if (CVarGetInteger(CVAR_ENHANCEMENT("LinkDefaultName"), 0) != 0) {
// Set player name to "リンク" ("Link" in Katakana, 3 characters long) when playing in Japanese.
defaultName = &linkNameJP;
this->newFileNameCharCount = 3;
} else {
defaultName = &emptyNameNES;
}
} else { // GAME_REGION_NTSC
defaultName = CVarGetInteger(CVAR_ENHANCEMENT("LinkDefaultName"), 0) ? &linkNameNES : &emptyNameNES;
}
@ -1544,6 +1549,7 @@ void FileChoose_UpdateRandomizerMenu(GameState* thisx) {
static u8 emptyNameNES[] = { 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF };
static u8 linkName[] = { 0x15, 0x2C, 0x31, 0x2E, 0x3E, 0x3E, 0x3E, 0x3E };
static u8 linkNameNES[] = { 0xB6, 0xB3, 0xB8, 0xB5, 0xDF, 0xDF, 0xDF, 0xDF };
static u8 linkNameJP[] = { 0x81, 0x87, 0x61, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF };
u8* defaultName;
this->prevConfigMode = this->configMode;
@ -1561,6 +1567,14 @@ void FileChoose_UpdateRandomizerMenu(GameState* thisx) {
this->nameEntryBoxAlpha = 0;
if (ResourceMgr_GetGameRegion(0) == GAME_REGION_PAL && gSaveContext.language != LANGUAGE_JPN) {
defaultName = CVarGetInteger(CVAR_ENHANCEMENT("LinkDefaultName"), 0) ? &linkName : &emptyName;
} else if (gSaveContext.language == LANGUAGE_JPN) { // Japanese
if (CVarGetInteger(CVAR_ENHANCEMENT("LinkDefaultName"), 0) != 0) {
// Set player name to "リンク" ("Link" in Katakana, 3 characters long) when playing in Japanese.
defaultName = &linkNameJP;
this->newFileNameCharCount = 3;
} else {
defaultName = &emptyNameNES;
}
} else { // GAME_REGION_NTSC
defaultName = CVarGetInteger(CVAR_ENHANCEMENT("LinkDefaultName"), 0) ? &linkNameNES : &emptyNameNES;
}