Shuffles: use ObjectExtension system for rando object identity (#5603)
Some checks are pending
generate-builds / generate-soh-otr (push) Waiting to run
generate-builds / build-macos (push) Blocked by required conditions
generate-builds / build-linux (push) Blocked by required conditions
generate-builds / build-windows (push) Blocked by required conditions

This commit is contained in:
Philip Dubé 2025-06-26 05:00:53 +00:00 committed by GitHub
commit 9e686ae6f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 142 additions and 105 deletions

View file

@ -1,6 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
#include "soh/Enhancements/randomizer/context.h"
extern "C" {
extern PlayState* gPlayState;

View file

@ -1,5 +1,6 @@
#include <soh/OTRGlobals.h>
#include "static_data.h"
#include "soh/ObjectExtension/ObjectExtension.h"
extern "C" {
#include "src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h"
@ -10,12 +11,14 @@ extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
void ObjComb_RandomizerChooseItemDrop(ObjComb* objComb, PlayState* play) {
s16 params = objComb->actor.params & 0x1F;
const auto beehiveIdentity = ObjectExtension::GetInstance().Get<BeehiveIdentity>(&objComb->actor);
if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf)) {
if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && beehiveIdentity != nullptr &&
!Flags_GetRandomizerInf(beehiveIdentity->randomizerInf)) {
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &objComb->actor.world.pos, ITEM00_SOH_DUMMY);
item00->randoInf = objComb->beehiveIdentity.randomizerInf;
item00->randoInf = beehiveIdentity->randomizerInf;
item00->itemEntry =
OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(objComb->beehiveIdentity.randomizerCheck, GI_NONE);
OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(beehiveIdentity->randomizerCheck, GI_NONE);
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
return;
}
@ -37,10 +40,11 @@ void ObjComb_RandomizerChooseItemDrop(ObjComb* objComb, PlayState* play) {
}
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)) {
const auto beehiveIdentity = ObjectExtension::GetInstance().Get<BeehiveIdentity>(&objComb->actor);
if (RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && beehiveIdentity == nullptr &&
!Flags_GetRandomizerInf(beehiveIdentity->randomizerInf)) {
if (objComb->unk_1B0 <= -5000) {
objComb->unk_1B0 = 1500;
}
@ -50,7 +54,7 @@ void ObjComb_RandomizerWait(ObjComb* objComb, PlayState* play) {
if ((objComb->collider.base.acFlags & AC_HIT) != 0) {
objComb->collider.base.acFlags &= ~AC_HIT;
dmgFlags = objComb->collider.elements[0].info.acHitInfo->toucher.dmgFlags;
s32 dmgFlags = objComb->collider.elements[0].info.acHitInfo->toucher.dmgFlags;
if (dmgFlags & 0x4001F866) {
objComb->unk_1B0 = 1500;
} else {
@ -70,8 +74,9 @@ void ObjComb_RandomizerWait(ObjComb* objComb, PlayState* play) {
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(
auto beehiveIdentity = OTRGlobals::Instance->gRandomizer->IdentifyBeehive(
gPlayState->sceneNum, (s16)objComb->actor.world.pos.x, respawnData);
ObjectExtension::GetInstance().Set<BeehiveIdentity>(actor, std::move(beehiveIdentity));
objComb->actionFunc = (ObjCombActionFunc)ObjComb_RandomizerWait;
}
@ -132,4 +137,5 @@ void Rando::StaticData::RegisterBeehiveLocations() {
// clang-format-on
}
static ObjectExtension::Register<BeehiveIdentity> RegisterBeehiveIdentity;
static RegisterShipInitFunc registerFunc(Rando::StaticData::RegisterBeehiveLocations);

View file

@ -1,9 +1,10 @@
#include "ShuffleCrates.h"
#include <soh/OTRGlobals.h>
#include "soh_assets.h"
#include "static_data.h"
#include <libultraship/libultra.h>
#include "global.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/ObjectExtension/ObjectExtension.h"
extern "C" {
#include "variables.h"
@ -31,8 +32,14 @@ extern "C" void ObjKibako2_RandomizerDraw(Actor* thisx, PlayState* play) {
return;
}
const auto crateIdentity = ObjectExtension::GetInstance().Get<CrateIdentity>(thisx);
if (crateIdentity == nullptr) {
Gfx_DrawDListOpa(play, (Gfx*)gLargeRandoCrateDL);
return;
}
GetItemEntry crateItem =
Rando::Context::GetInstance()->GetFinalGIEntry(crateActor->crateIdentity.randomizerCheck, true, GI_NONE);
Rando::Context::GetInstance()->GetFinalGIEntry(crateIdentity->randomizerCheck, true, GI_NONE);
getItemCategory = crateItem.getItemCategory;
// If they have bombchus, don't consider the bombchu item major
@ -99,8 +106,14 @@ extern "C" void ObjKibako_RandomizerDraw(Actor* thisx, PlayState* play) {
return;
}
GetItemEntry smallCrateItem = Rando::Context::GetInstance()->GetFinalGIEntry(
smallCrateActor->smallCrateIdentity.randomizerCheck, true, GI_NONE);
const auto crateIdentity = ObjectExtension::GetInstance().Get<SmallCrateIdentity>(thisx);
if (crateIdentity == nullptr) {
Gfx_DrawDListOpa(play, (Gfx*)gSmallRandoCrateDL);
return;
}
GetItemEntry smallCrateItem =
Rando::Context::GetInstance()->GetFinalGIEntry(crateIdentity->randomizerCheck, true, GI_NONE);
getItemCategory = smallCrateItem.getItemCategory;
// If they have bombchus, don't consider the bombchu item major
@ -154,15 +167,19 @@ extern "C" void ObjKibako_RandomizerDraw(Actor* thisx, PlayState* play) {
}
uint8_t ObjKibako2_RandomizerHoldsItem(ObjKibako2* crateActor, PlayState* play) {
RandomizerCheck rc = crateActor->crateIdentity.randomizerCheck;
const auto crateIdentity = ObjectExtension::GetInstance().Get<CrateIdentity>(&crateActor->dyna.actor);
if (crateIdentity == nullptr) {
return false;
}
RandomizerCheck rc = crateIdentity->randomizerCheck;
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
uint8_t crateSetting = RAND_GET_OPTION(RSK_SHUFFLE_CRATES);
// Don't pull randomized item if crate isn't randomized or is already checked
if (!IS_RANDO || (crateSetting == RO_SHUFFLE_CRATES_OVERWORLD && isDungeon) ||
(crateSetting == RO_SHUFFLE_CRATES_DUNGEONS && !isDungeon) ||
Flags_GetRandomizerInf(crateActor->crateIdentity.randomizerInf) ||
crateActor->crateIdentity.randomizerCheck == RC_UNKNOWN_CHECK) {
Flags_GetRandomizerInf(crateIdentity->randomizerInf) || crateIdentity->randomizerCheck == RC_UNKNOWN_CHECK) {
return false;
} else {
return true;
@ -170,15 +187,19 @@ uint8_t ObjKibako2_RandomizerHoldsItem(ObjKibako2* crateActor, PlayState* play)
}
uint8_t ObjKibako_RandomizerHoldsItem(ObjKibako* smallCrateActor, PlayState* play) {
RandomizerCheck rc = smallCrateActor->smallCrateIdentity.randomizerCheck;
const auto crateIdentity = ObjectExtension::GetInstance().Get<SmallCrateIdentity>(&smallCrateActor->actor);
if (crateIdentity == nullptr) {
return false;
}
RandomizerCheck rc = crateIdentity->randomizerCheck;
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
uint8_t crateSetting = RAND_GET_OPTION(RSK_SHUFFLE_CRATES);
// Don't pull randomized item if crate isn't randomized or is already checked
if (!IS_RANDO || (crateSetting == RO_SHUFFLE_CRATES_OVERWORLD && isDungeon) ||
(crateSetting == RO_SHUFFLE_CRATES_DUNGEONS && !isDungeon) ||
Flags_GetRandomizerInf(smallCrateActor->smallCrateIdentity.randomizerInf) ||
smallCrateActor->smallCrateIdentity.randomizerCheck == RC_UNKNOWN_CHECK) {
Flags_GetRandomizerInf(crateIdentity->randomizerInf) || crateIdentity->randomizerCheck == RC_UNKNOWN_CHECK) {
return false;
} else {
return true;
@ -186,10 +207,14 @@ uint8_t ObjKibako_RandomizerHoldsItem(ObjKibako* smallCrateActor, PlayState* pla
}
void ObjKibako2_RandomizerSpawnCollectible(ObjKibako2* crateActor, PlayState* play) {
const auto crateIdentity = ObjectExtension::GetInstance().Get<CrateIdentity>(&crateActor->dyna.actor);
if (crateIdentity == nullptr) {
return;
}
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &crateActor->dyna.actor.world.pos, ITEM00_SOH_DUMMY);
item00->randoInf = crateActor->crateIdentity.randomizerInf;
item00->itemEntry =
Rando::Context::GetInstance()->GetFinalGIEntry(crateActor->crateIdentity.randomizerCheck, true, GI_NONE);
item00->randoInf = crateIdentity->randomizerInf;
item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(crateIdentity->randomizerCheck, true, GI_NONE);
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f;
@ -197,10 +222,14 @@ void ObjKibako2_RandomizerSpawnCollectible(ObjKibako2* crateActor, PlayState* pl
}
void ObjKibako_RandomizerSpawnCollectible(ObjKibako* smallCrateActor, PlayState* play) {
const auto crateIdentity = ObjectExtension::GetInstance().Get<SmallCrateIdentity>(&smallCrateActor->actor);
if (crateIdentity == nullptr) {
return;
}
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &smallCrateActor->actor.world.pos, ITEM00_SOH_DUMMY);
item00->randoInf = smallCrateActor->smallCrateIdentity.randomizerInf;
item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(
smallCrateActor->smallCrateIdentity.randomizerCheck, true, GI_NONE);
item00->randoInf = crateIdentity->randomizerInf;
item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(crateIdentity->randomizerCheck, true, GI_NONE);
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f;
@ -231,8 +260,9 @@ void ObjKibako2_RandomizerInit(void* actorRef) {
ObjKibako2* crateActor = static_cast<ObjKibako2*>(actorRef);
crateActor->crateIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCrate(
gPlayState->sceneNum, (s16)actor->world.pos.x, (s16)actor->world.pos.z);
auto crateIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCrate(gPlayState->sceneNum, (s16)actor->world.pos.x,
(s16)actor->world.pos.z);
ObjectExtension::GetInstance().Set<CrateIdentity>(actor, std::move(crateIdentity));
}
void ObjKibako_RandomizerInit(void* actorRef) {
@ -243,8 +273,9 @@ void ObjKibako_RandomizerInit(void* actorRef) {
ObjKibako* smallCrateActor = static_cast<ObjKibako*>(actorRef);
smallCrateActor->smallCrateIdentity = OTRGlobals::Instance->gRandomizer->IdentifySmallCrate(
auto crateIdentity = OTRGlobals::Instance->gRandomizer->IdentifySmallCrate(
gPlayState->sceneNum, (s16)actor->home.pos.x, (s16)actor->home.pos.z);
ObjectExtension::GetInstance().Set<SmallCrateIdentity>(actor, std::move(crateIdentity));
}
void RegisterShuffleCrates() {
@ -564,5 +595,7 @@ void Rando::StaticData::RegisterCrateLocations() {
// clang-format on
}
static ObjectExtension::Register<CrateIdentity> RegisterCrateIdentity;
static ObjectExtension::Register<SmallCrateIdentity> RegisterSmallCrateIdentity;
static RegisterShipInitFunc initFunc(RegisterShuffleCrates, { "IS_RANDO" });
static RegisterShipInitFunc locFunc(Rando::StaticData::RegisterCrateLocations);

View file

@ -1,16 +0,0 @@
#ifndef ShuffleCrates_H
#define ShuffleCrates_H
#include <z64.h>
#include <soh/OTRGlobals.h>
#ifdef __cplusplus
extern "C" {
#endif
void ObjKibako2_RandomizerInit(void* actorRef);
void ObjKibako_RandomizerInit(void* actorRef);
#ifdef __cplusplus
};
#endif
#endif // ShuffleCrates_H

View file

@ -1,19 +1,28 @@
#include "soh/OTRGlobals.h"
#include "randomizer_grotto.h"
#include "draw.h"
#include "soh/cvar_prefixes.h"
#include "static_data.h"
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
#include "soh/ObjectExtension/ObjectExtension.h"
extern "C" {
#include "src/overlays/actors/ovl_En_Elf/z_en_elf.h"
#include "src/overlays/actors/ovl_Obj_Bean/z_obj_bean.h"
#include "src/overlays/actors/ovl_En_Gs/z_en_gs.h"
#include "src/overlays/actors/ovl_Shot_Sun/z_shot_sun.h"
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
#include "static_data.h"
}
#define FAIRY_FLAG_TIMED (1 << 8)
void ShuffleFairies_DrawRandomizedItem(EnElf* enElf, PlayState* play) {
const auto fairyIdentity = ObjectExtension::GetInstance().Get<FairyIdentity>(&enElf->actor);
if (fairyIdentity == nullptr) {
return;
}
GetItemEntry randoGetItem =
Rando::Context::GetInstance()->GetFinalGIEntry(enElf->sohFairyIdentity.randomizerCheck, true, GI_FAIRY);
Rando::Context::GetInstance()->GetFinalGIEntry(fairyIdentity->randomizerCheck, true, GI_FAIRY);
if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) {
randoGetItem = GET_ITEM_MYSTERY;
}
@ -33,8 +42,8 @@ bool ShuffleFairies_FairyExists(FairyIdentity fairyIdentity) {
if (actor->id != ACTOR_EN_ELF) {
actor = actor->next;
} else {
EnElf* enElf = (EnElf*)(actor);
if (fairyIdentity.randomizerInf == enElf->sohFairyIdentity.randomizerInf) {
const auto actorFairyIdentity = ObjectExtension::GetInstance().Get<FairyIdentity>(&actor);
if (actorFairyIdentity != nullptr && fairyIdentity.randomizerInf == actorFairyIdentity->randomizerInf) {
return true;
}
actor = actor->next;
@ -70,10 +79,10 @@ FairyIdentity ShuffleFairies_GetFairyIdentity(int32_t params) {
static bool SpawnFairy(f32 posX, f32 posY, f32 posZ, int32_t params, FairyType fairyType) {
FairyIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params);
if (!Flags_GetRandomizerInf(fairyIdentity.randomizerInf)) {
EnElf* fairy = (EnElf*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_ELF, posX, posY - 30.0f, posZ, 0,
0, 0, fairyType, true);
fairy->sohFairyIdentity = fairyIdentity;
fairy->actor.draw = (ActorFunc)ShuffleFairies_DrawRandomizedItem;
Actor* fairy = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_ELF, posX, posY - 30.0f, posZ, 0, 0, 0,
fairyType, true);
ObjectExtension::GetInstance().Set<FairyIdentity>(fairy, std::move(fairyIdentity));
fairy->draw = (ActorFunc)ShuffleFairies_DrawRandomizedItem;
return true;
}
return false;
@ -85,8 +94,14 @@ void RegisterShuffleFairies() {
// Grant item when picking up fairy.
COND_VB_SHOULD(VB_FAIRY_HEAL, shouldRegister, {
EnElf* enElf = va_arg(args, EnElf*);
if (enElf->sohFairyIdentity.randomizerInf && enElf->sohFairyIdentity.randomizerInf != RAND_INF_MAX) {
Flags_SetRandomizerInf(enElf->sohFairyIdentity.randomizerInf);
const auto fairyIdentity = ObjectExtension::GetInstance().Get<FairyIdentity>(&enElf->actor);
if (fairyIdentity == nullptr) {
return;
}
if (fairyIdentity != nullptr && fairyIdentity->randomizerInf && fairyIdentity->randomizerInf != RAND_INF_MAX) {
Flags_SetRandomizerInf(fairyIdentity->randomizerInf);
}
});
@ -404,5 +419,6 @@ void Rando::StaticData::RegisterFairyLocations() {
// clang-format on
}
static ObjectExtension::Register<FairyIdentity> RegisterFairyIdentity;
static RegisterShipInitFunc registerShuffleFairies(RegisterShuffleFairies, { "IS_RANDO" });
static RegisterShipInitFunc registerShuffleFairiesLocations(Rando::StaticData::RegisterFairyLocations);

View file

@ -1,6 +1,7 @@
#include "ShuffleGrass.h"
#include <soh/OTRGlobals.h>
#include "soh_assets.h"
#include "static_data.h"
#include "soh/ObjectExtension/ObjectExtension.h"
#include "soh/Enhancements/enhancementTypes.h"
extern "C" {
@ -27,18 +28,20 @@ extern "C" void EnKusa_RandomizerDraw(Actor* thisx, PlayState* play) {
static Gfx* dLists[] = { (Gfx*)gRandoBushJunkDL, (Gfx*)gRandoCuttableGrassJunkDL, (Gfx*)gRandoCuttableGrassJunkDL };
auto grassActor = ((EnKusa*)thisx);
const auto grassIdentity = ObjectExtension::GetInstance().Get<GrassIdentity>(thisx);
OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
if (grassActor->grassIdentity.randomizerCheck != RC_MAX &&
Flags_GetRandomizerInf(grassActor->grassIdentity.randomizerInf) == 0) {
if (grassIdentity != nullptr && grassIdentity->randomizerCheck != RC_MAX &&
Flags_GetRandomizerInf(grassIdentity->randomizerInf) == 0) {
int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED);
int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0);
if ((csmc == CSMC_BOTH || csmc == CSMC_TEXTURE) &&
(!requiresStoneAgony || (requiresStoneAgony && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) {
auto itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(grassActor->grassIdentity.randomizerCheck,
true, GI_NONE);
auto itemEntry =
Rando::Context::GetInstance()->GetFinalGIEntry(grassIdentity->randomizerCheck, true, GI_NONE);
GetItemCategory getItemCategory = itemEntry.getItemCategory;
switch (getItemCategory) {
@ -88,19 +91,19 @@ extern "C" void EnKusa_RandomizerDraw(Actor* thisx, PlayState* play) {
}
uint8_t EnKusa_RandomizerHoldsItem(EnKusa* grassActor, PlayState* play) {
if (grassActor->grassIdentity.randomizerCheck == RC_MAX)
const auto grassIdentity = ObjectExtension::GetInstance().Get<GrassIdentity>(&grassActor->actor);
if (grassIdentity == nullptr || grassIdentity->randomizerCheck == RC_MAX)
return false;
RandomizerCheck rc = grassActor->grassIdentity.randomizerCheck;
RandomizerCheck rc = grassIdentity->randomizerCheck;
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
uint8_t grassSetting = RAND_GET_OPTION(RSK_SHUFFLE_GRASS);
// Don't pull randomized item if grass isn't randomized or is already checked
if (!IS_RANDO || (grassSetting == RO_SHUFFLE_GRASS_OVERWORLD && isDungeon) ||
(grassSetting == RO_SHUFFLE_GRASS_DUNGEONS && !isDungeon) ||
Flags_GetRandomizerInf(grassActor->grassIdentity.randomizerInf) ||
grassActor->grassIdentity.randomizerCheck == RC_UNKNOWN_CHECK) {
Flags_GetRandomizerInf(grassIdentity->randomizerInf) || rc == RC_UNKNOWN_CHECK) {
return false;
} else {
return true;
@ -108,10 +111,14 @@ uint8_t EnKusa_RandomizerHoldsItem(EnKusa* grassActor, PlayState* play) {
}
void EnKusa_RandomizerSpawnCollectible(EnKusa* grassActor, PlayState* play) {
const auto grassIdentity = ObjectExtension::GetInstance().Get<GrassIdentity>(&grassActor->actor);
if (grassIdentity == nullptr) {
return;
}
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &grassActor->actor.world.pos, ITEM00_SOH_DUMMY);
item00->randoInf = grassActor->grassIdentity.randomizerInf;
item00->itemEntry =
Rando::Context::GetInstance()->GetFinalGIEntry(grassActor->grassIdentity.randomizerCheck, true, GI_NONE);
item00->randoInf = grassIdentity->randomizerInf;
item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(grassIdentity->randomizerCheck, true, GI_NONE);
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f;
@ -127,8 +134,9 @@ void EnKusa_RandomizerInit(void* actorRef) {
EnKusa* grassActor = static_cast<EnKusa*>(actorRef);
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
grassActor->grassIdentity = OTRGlobals::Instance->gRandomizer->IdentifyGrass(
auto grassIdentity = OTRGlobals::Instance->gRandomizer->IdentifyGrass(
gPlayState->sceneNum, (s16)actor->world.pos.x, (s16)actor->world.pos.z, respawnData, gPlayState->linkAgeOnLoad);
ObjectExtension::GetInstance().Set<GrassIdentity>(actor, std::move(grassIdentity));
}
void RegisterShuffleGrass() {
@ -150,8 +158,10 @@ void RegisterShuffleGrass() {
EnKusa* grassActor = va_arg(args, EnKusa*);
if (EnKusa_RandomizerHoldsItem(grassActor, gPlayState)) {
EnKusa_RandomizerSpawnCollectible(grassActor, gPlayState);
grassActor->grassIdentity.randomizerCheck = RC_MAX;
grassActor->grassIdentity.randomizerInf = RAND_INF_MAX;
ObjectExtension::GetInstance().Set<GrassIdentity>(&grassActor->actor, std::move(GrassIdentity{
.randomizerInf = RAND_INF_MAX,
.randomizerCheck = RC_MAX,
}));
*should = false;
} else {
*should = true;
@ -519,5 +529,6 @@ void Rando::StaticData::RegisterGrassLocations() {
// clang-format on
}
static ObjectExtension::Register<GrassIdentity> RegisterGrassIdentity;
static RegisterShipInitFunc registerShuffleGrass(RegisterShuffleGrass, { "IS_RANDO" });
static RegisterShipInitFunc registerShuffleGrassLocations(Rando::StaticData::RegisterGrassLocations);

View file

@ -1,15 +0,0 @@
#ifndef SHUFFLEGRASS_H
#define SHUFFLEGRASS_H
#include <z64.h>
#include <soh/OTRGlobals.h>
#ifdef __cplusplus
extern "C" {
#endif
void EnKusa_RandomizerInit(void* actorRef);
#ifdef __cplusplus
};
#endif
#endif // SHUFFLEGRASS_H

View file

@ -1,6 +1,7 @@
#include "soh/OTRGlobals.h"
#include "soh_assets.h"
#include "static_data.h"
#include "soh/ObjectExtension/ObjectExtension.h"
extern "C" {
#include "variables.h"
@ -25,15 +26,19 @@ extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) {
}
uint8_t ObjTsubo_RandomizerHoldsItem(ObjTsubo* potActor, PlayState* play) {
RandomizerCheck rc = potActor->potIdentity.randomizerCheck;
const auto potIdentity = ObjectExtension::GetInstance().Get<PotIdentity>(&potActor->actor);
if (potIdentity == nullptr) {
return false;
}
RandomizerCheck rc = potIdentity->randomizerCheck;
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
uint8_t potSetting = RAND_GET_OPTION(RSK_SHUFFLE_POTS);
// Don't pull randomized item if pot isn't randomized or is already checked
if (!IS_RANDO || (potSetting == RO_SHUFFLE_POTS_OVERWORLD && isDungeon) ||
(potSetting == RO_SHUFFLE_POTS_DUNGEONS && !isDungeon) ||
Flags_GetRandomizerInf(potActor->potIdentity.randomizerInf) ||
potActor->potIdentity.randomizerCheck == RC_UNKNOWN_CHECK) {
(potSetting == RO_SHUFFLE_POTS_DUNGEONS && !isDungeon) || Flags_GetRandomizerInf(potIdentity->randomizerInf) ||
potIdentity->randomizerCheck == RC_UNKNOWN_CHECK) {
return false;
} else {
return true;
@ -41,10 +46,14 @@ uint8_t ObjTsubo_RandomizerHoldsItem(ObjTsubo* potActor, PlayState* play) {
}
void ObjTsubo_RandomizerSpawnCollectible(ObjTsubo* potActor, PlayState* play) {
const auto potIdentity = ObjectExtension::GetInstance().Get<PotIdentity>(&potActor->actor);
if (potIdentity == nullptr) {
return;
}
EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &potActor->actor.world.pos, ITEM00_SOH_DUMMY);
item00->randoInf = potActor->potIdentity.randomizerInf;
item00->itemEntry =
Rando::Context::GetInstance()->GetFinalGIEntry(potActor->potIdentity.randomizerCheck, true, GI_NONE);
item00->randoInf = potIdentity->randomizerInf;
item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(potIdentity->randomizerCheck, true, GI_NONE);
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f;
@ -58,8 +67,9 @@ void RegisterShufflePots() {
Actor* actor = static_cast<Actor*>(actorRef);
ObjTsubo* potActor = static_cast<ObjTsubo*>(actorRef);
potActor->potIdentity = OTRGlobals::Instance->gRandomizer->IdentifyPot(
gPlayState->sceneNum, (s16)actor->world.pos.x, (s16)actor->world.pos.z);
auto potIdentity = OTRGlobals::Instance->gRandomizer->IdentifyPot(gPlayState->sceneNum, (s16)actor->world.pos.x,
(s16)actor->world.pos.z);
ObjectExtension::GetInstance().Set<PotIdentity>(actor, std::move(potIdentity));
});
// Draw custom model for pot to indicate it holding a randomized item.
@ -649,5 +659,6 @@ void Rando::StaticData::RegisterPotLocations() {
// clang-format on
}
static ObjectExtension::Register<PotIdentity> RegisterPotIdentity;
static RegisterShipInitFunc registerShufflePots(RegisterShufflePots, { "IS_RANDO" });
static RegisterShipInitFunc registerShufflePotLocations(Rando::StaticData::RegisterPotLocations);

View file

@ -42,9 +42,6 @@ typedef struct EnElf {
/* 0x02C7 */ u8 unk_2C7;
/* 0x02C8 */ EnElfUnkFunc func_2C8;
/* 0x02CC */ EnElfActionFunc actionFunc;
// #region SOH [Randomizer]
/* */ FairyIdentity sohFairyIdentity;
// #endregion
} EnElf; // size = 0x02D0
typedef enum {

View file

@ -20,7 +20,6 @@ typedef struct EnKusa {
/* 0x0150 */ ColliderCylinder collider;
/* 0x019C */ s16 timer;
/* 0x019E */ s8 objBankIndex;
/* */ GrassIdentity grassIdentity;
} EnKusa; // size = 0x01A0
#endif

View file

@ -15,7 +15,6 @@ typedef struct ObjComb {
/* 0x0170 */ ColliderJntSphElement colliderItems[1];
/* 0x01B0 */ s16 unk_1B0;
/* 0x01B2 */ s16 unk_1B2;
/* */ BeehiveIdentity beehiveIdentity;
} ObjComb; // size = 0x01B4
void ObjComb_Break(ObjComb* objComb, PlayState* play);

View file

@ -12,7 +12,6 @@ typedef struct ObjKibako {
/* 0x0000 */ Actor actor;
/* 0x014C */ ObjKibakoActionFunc actionFunc;
/* 0x0150 */ ColliderCylinder collider;
/* */ SmallCrateIdentity smallCrateIdentity;
} ObjKibako; // size = 0x019C
#endif

View file

@ -13,7 +13,6 @@ typedef struct ObjKibako2 {
/* 0x0164 */ ColliderCylinder collider;
/* 0x01B0 */ ObjKibako2ActionFunc actionFunc;
/* 0x01B4 */ s16 collectibleFlag;
/* */ CrateIdentity crateIdentity;
} ObjKibako2; // size = 0x01B8
#endif

View file

@ -13,7 +13,6 @@ typedef struct ObjTsubo {
/* 0x014C */ ObjTsuboActionFunc actionFunc;
/* 0x0150 */ ColliderCylinder collider;
/* 0x019C */ s8 objTsuboBankIndex;
/* */ PotIdentity potIdentity;
} ObjTsubo; // size = 0x01A0
#endif