VBify pots progress

This commit is contained in:
aMannus 2024-08-28 11:14:04 +02:00
parent ba447276df
commit d5ba83a814
8 changed files with 158 additions and 62 deletions

View File

@ -242,6 +242,9 @@ typedef enum {
``` ```
*/ */
VB_DRAW_AMMO_COUNT, VB_DRAW_AMMO_COUNT,
// Opt: *ObjTsubo
VB_POT_DRAW,
VB_POT_DROP_ITEM,
/*** Play Cutscenes ***/ /*** Play Cutscenes ***/

View File

@ -64,6 +64,9 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void));
//Mark: - Pause Menu //Mark: - Pause Menu
void GameInteractor_ExecuteOnKaleidoUpdate(); void GameInteractor_ExecuteOnKaleidoUpdate();
//Mark - Randomizer options spawning EnItem00 actors
void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -14,6 +14,7 @@
#include "soh/Enhancements/TimeSavers/TimeSavers.h" #include "soh/Enhancements/TimeSavers/TimeSavers.h"
#include "soh/Enhancements/cheat_hook_handlers.h" #include "soh/Enhancements/cheat_hook_handlers.h"
#include "soh/Enhancements/randomizer/hook_handlers.h" #include "soh/Enhancements/randomizer/hook_handlers.h"
#include "soh/Enhancements/randomizer/ShufflePots.h"
#include "objects/object_gi_compass/object_gi_compass.h" #include "objects/object_gi_compass/object_gi_compass.h"
#include "src/overlays/actors/ovl_En_Bb/z_en_bb.h" #include "src/overlays/actors/ovl_En_Bb/z_en_bb.h"
@ -1822,4 +1823,5 @@ void InitMods() {
RegisterHurtContainerModeHandler(); RegisterHurtContainerModeHandler();
RegisterPauseMenuHooks(); RegisterPauseMenuHooks();
RegisterSkeletonKey(); RegisterSkeletonKey();
RegisterShufflePots();
} }

View File

@ -0,0 +1,126 @@
#include "ShufflePots.h"
#include "soh_assets.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
extern "C" {
#include "overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.h"
#include "variables.h"
u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
PotIdentity Randomizer_IdentifyPot(s32 sceneNum, s32 posX, s32 posZ);
extern PlayState* gPlayState;
}
extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) {
float potSize = 1.0f;
OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
Matrix_Scale(potSize, potSize, potSize, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gRandoPotDL);
CLOSE_DISPS(play->state.gfxCtx);
}
uint8_t ObjTsubo_RandomizerHoldsItem(ObjTsubo* potActor, PlayState* play) {
uint8_t isDungeon =
play->sceneNum < SCENE_GANONS_TOWER_COLLAPSE_INTERIOR ||
(play->sceneNum > SCENE_TREASURE_BOX_SHOP && play->sceneNum < SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR);
uint8_t potSetting = Randomizer_GetSettingValue(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) {
return false;
} else {
return true;
}
}
uint8_t ObjTsubo_RandomizerSkipItemCutscene(ObjTsubo* potActor) {
/*return
potActor->actor.params == ITEM00_SMALL_KEY && giEntry.modIndex == MOD_NONE &&
((giEntry.itemId >= ITEM_RUPEE_GREEN && giEntry.itemId <= ITEM_RUPEE_RED) || giEntry.itemId == ITEM_HEART ||
(giEntry.itemId >= ITEM_NUTS_5 && giEntry.itemId <= ITEM_SEEDS_30) || giEntry.itemId == ITEM_MAGIC_SMALL ||
giEntry.itemId == ITEM_MAGIC_LARGE);*/
}
void ObjTsubo_RandomizerSpawnCollectible(ObjTsubo* potActor) {
EnItem00* item00 =
(EnItem00*)Item_DropCollectible2(gPlayState, &potActor->actor.world.pos, ITEM00_SOH_GIVE_ITEM_ENTRY);
item00->randoInf = potActor->potIdentity.randomizerInf;
item00->itemEntry =
OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(potActor->potIdentity.randomizerCheck, GI_NONE);
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
item00->actor.velocity.y = 8.0f;
item00->actor.speedXZ = 2.0f;
item00->actor.gravity = -0.9f;
item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f);
}
void ObjTsubo_RandomizerInit(void* actorRef) {
Actor* actor = static_cast<Actor*>(actorRef);
if (actor->id != ACTOR_OBJ_TSUBO) return;
ObjTsubo* potActor = static_cast<ObjTsubo*>(actorRef);
potActor->potIdentity =
Randomizer_IdentifyPot(gPlayState->sceneNum, (s16)actor->world.pos.x, (s16)actor->world.pos.z);
if (ObjTsubo_RandomizerHoldsItem(potActor, gPlayState)) {
potActor->potIdentity.isShuffled = true;
} else {
potActor->potIdentity.isShuffled = false;
}
}
void PotOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* optionalArg) {
ObjTsubo* potActor = static_cast<ObjTsubo*>(optionalArg);
switch (id) {
case VB_POT_DRAW: {
if (potActor->potIdentity.isShuffled) {
*should = false;
potActor->actor.draw = (ActorFunc)ObjTsubo_RandomizerDraw;
}
break;
}
case VB_POT_DROP_ITEM: {
if (potActor->potIdentity.isShuffled) {
*should = false;
ObjTsubo_RandomizerSpawnCollectible(potActor);
}
break;
}
}
}
void RegisterShufflePots() {
static uint32_t onActorInitHook = 0;
static uint32_t onVanillaBehaviorHook = 0;
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(onActorInitHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(onVanillaBehaviorHook);
onActorInitHook = 0;
onVanillaBehaviorHook = 0;
if (!IS_RANDO) return;
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_POTS)) return;
onActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(ObjTsubo_RandomizerInit);
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(PotOnVanillaBehaviorHandler);
});
}

View File

@ -0,0 +1,15 @@
#ifndef SHUFFLEPOTS_H
#define SHUFFLEPOTS_H
#include "z64.h"
#ifdef __cplusplus
extern "C" {
#endif
void ObjTsubo_RandomizerDraw(Actor* potActor, PlayState* play);
void RegisterShufflePots();
#ifdef __cplusplus
};
#endif
#endif //SHUFFLEPOTS_H

View File

@ -4899,6 +4899,7 @@ typedef struct CowIdentity {
typedef struct PotIdentity { typedef struct PotIdentity {
RandomizerInf randomizerInf; RandomizerInf randomizerInf;
RandomizerCheck randomizerCheck; RandomizerCheck randomizerCheck;
uint8_t isShuffled;
} PotIdentity; } PotIdentity;
typedef struct FishIdentity { typedef struct FishIdentity {

View File

@ -8,7 +8,7 @@
#include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h" #include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h"
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" #include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
#include "objects/object_tsubo/object_tsubo.h" #include "objects/object_tsubo/object_tsubo.h"
#include "soh_assets.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_ALWAYS_THROWN) #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_ALWAYS_THROWN)
@ -84,43 +84,11 @@ static InitChainEntry sInitChain[] = {
ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 800, ICHAIN_STOP), ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 800, ICHAIN_STOP),
}; };
s8 ObjTsubo_HoldsRandomizedItem(ObjTsubo* this, PlayState* play) {
uint8_t isDungeon = play->sceneNum < SCENE_GANONS_TOWER_COLLAPSE_INTERIOR ||
(play->sceneNum > SCENE_TREASURE_BOX_SHOP && play->sceneNum < SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR);
uint8_t potSetting = Randomizer_GetSettingValue(RSK_SHUFFLE_POTS);
// Don't pull randomized item if pot isn't randomized or is already checked
if (!IS_RANDO || !potSetting ||
(potSetting == RO_SHUFFLE_POTS_OVERWORLD && isDungeon) ||
(potSetting == RO_SHUFFLE_POTS_DUNGEONS && !isDungeon) ||
Flags_GetRandomizerInf(this->potIdentity.randomizerInf) ||
this->potIdentity.randomizerCheck == RC_UNKNOWN_CHECK) {
return false;
} else {
return true;
}
}
void ObjTsubo_SpawnCollectible(ObjTsubo* this, PlayState* play) { void ObjTsubo_SpawnCollectible(ObjTsubo* this, PlayState* play) {
if (IS_RANDO && ObjTsubo_HoldsRandomizedItem(this, play)) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(this->potIdentity.randomizerCheck, GI_NONE);
EnItem00* actor = (EnItem00*)Item_DropCollectible2(play, &this->actor.world.pos, ITEM00_SMALL_KEY);
actor->randoCheck = this->potIdentity.randomizerCheck;
actor->randoGiEntry = getItemEntry;
actor->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING;
actor->randoInf = this->potIdentity.randomizerInf;
actor->actor.velocity.y = 8.0f;
actor->actor.speedXZ = 2.0f;
actor->actor.gravity = -0.9f;
actor->actor.world.rot.y = Rand_CenteredFloat(65536.0f);
return;
}
s16 dropParams = this->actor.params & 0x1F; s16 dropParams = this->actor.params & 0x1F;
if ((dropParams >= ITEM00_RUPEE_GREEN) && (dropParams <= ITEM00_BOMBS_SPECIAL)) { if ((dropParams >= ITEM00_RUPEE_GREEN) && (dropParams <= ITEM00_BOMBS_SPECIAL) &&
GameInteractor_Should(VB_POT_DROP_ITEM, true, this)) {
Item_DropCollectible(play, &this->actor.world.pos, Item_DropCollectible(play, &this->actor.world.pos,
(dropParams | (((this->actor.params >> 9) & 0x3F) << 8))); (dropParams | (((this->actor.params >> 9) & 0x3F) << 8)));
} }
@ -179,9 +147,6 @@ void ObjTsubo_Init(Actor* thisx, PlayState* play) {
ObjTsubo_SetupWaitForObject(this); ObjTsubo_SetupWaitForObject(this);
osSyncPrintf("(dungeon keep 壷)(arg_data 0x%04x)\n", this->actor.params); osSyncPrintf("(dungeon keep 壷)(arg_data 0x%04x)\n", this->actor.params);
} }
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_POTS)) {
this->potIdentity = Randomizer_IdentifyPot(play->sceneNum, (s16)this->actor.world.pos.x, (s16)this->actor.world.pos.z);
}
} }
void ObjTsubo_Destroy(Actor* thisx, PlayState* play2) { void ObjTsubo_Destroy(Actor* thisx, PlayState* play2) {
@ -268,7 +233,9 @@ void ObjTsubo_SetupWaitForObject(ObjTsubo* this) {
void ObjTsubo_WaitForObject(ObjTsubo* this, PlayState* play) { void ObjTsubo_WaitForObject(ObjTsubo* this, PlayState* play) {
if (Object_IsLoaded(&play->objectCtx, this->objTsuboBankIndex)) { if (Object_IsLoaded(&play->objectCtx, this->objTsuboBankIndex)) {
this->actor.draw = ObjTsubo_Draw; if (GameInteractor_Should(VB_POT_DRAW, true, this)) {
this->actor.draw = ObjTsubo_Draw;
}
this->actor.objBankIndex = this->objTsuboBankIndex; this->actor.objBankIndex = this->objTsuboBankIndex;
ObjTsubo_SetupIdle(this); ObjTsubo_SetupIdle(this);
this->actor.flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED; this->actor.flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED;
@ -381,18 +348,5 @@ void ObjTsubo_Update(Actor* thisx, PlayState* play) {
void ObjTsubo_Draw(Actor* thisx, PlayState* play) { void ObjTsubo_Draw(Actor* thisx, PlayState* play) {
ObjTsubo* this = (ObjTsubo*)thisx; ObjTsubo* this = (ObjTsubo*)thisx;
if (IS_RANDO && ObjTsubo_HoldsRandomizedItem(this, play)) { Gfx_DrawDListOpa(play, D_80BA1B84[(thisx->params >> 8) & 1]);
float potSize = 1.0f;
OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
Matrix_Scale(potSize, potSize, potSize, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gRandoPotDL);
CLOSE_DISPS(play->state.gfxCtx);
} else {
Gfx_DrawDListOpa(play, D_80BA1B84[(thisx->params >> 8) & 1]);
}
} }

View File

@ -6821,16 +6821,8 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) {
// this specifically for items coming from bushes/rocks/enemies when the player has already picked that item up. // this specifically for items coming from bushes/rocks/enemies when the player has already picked that item up.
uint8_t skipItemCutsceneRando = IS_RANDO && Item_CheckObtainability(giEntry.itemId) != ITEM_NONE && isDropToSkip; uint8_t skipItemCutsceneRando = IS_RANDO && Item_CheckObtainability(giEntry.itemId) != ITEM_NONE && isDropToSkip;
// Automatically skip the pickup messages for very frequent items coming from pots with "Shuffle Pots" on.
uint8_t isPotItemToSkip = interactedActor->id == ACTOR_EN_ITEM00 &&
interactedActor->params == ITEM00_SMALL_KEY && giEntry.modIndex == MOD_NONE &&
((giEntry.itemId >= ITEM_RUPEE_GREEN && giEntry.itemId <= ITEM_RUPEE_RED) ||
giEntry.itemId == ITEM_HEART ||
(giEntry.itemId >= ITEM_NUTS_5 && giEntry.itemId <= ITEM_SEEDS_30) ||
giEntry.itemId == ITEM_MAGIC_SMALL || giEntry.itemId == ITEM_MAGIC_LARGE);
// Show cutscene when picking up a item. // Show cutscene when picking up a item.
if (showItemCutscene && !skipItemCutscene && !skipItemCutsceneRando && !isPotItemToSkip) { if (showItemCutscene && !skipItemCutscene && !skipItemCutsceneRando) {
Player_DetachHeldActor(play, this); Player_DetachHeldActor(play, this);
func_8083AE40(this, giEntry.objectId); func_8083AE40(this, giEntry.objectId);