Skip to content

Commit

Permalink
SceneDB
Browse files Browse the repository at this point in the history
  • Loading branch information
Rozelette committed Dec 6, 2024
1 parent c3e4579 commit 04df12b
Show file tree
Hide file tree
Showing 36 changed files with 4,620 additions and 978 deletions.
3 changes: 2 additions & 1 deletion soh/include/z64.h
Original file line number Diff line number Diff line change
Expand Up @@ -1675,7 +1675,8 @@ typedef struct PreNMIContext {
} PreNMIContext; // size = 0xAC

typedef enum {
/* 1 */ F_8F = 1,
/* 0 */ F_NA,
/* 1 */ F_8F,
/* 2 */ F_7F,
/* 3 */ F_6F,
/* 4 */ F_5F,
Expand Down
6 changes: 3 additions & 3 deletions soh/include/z64save.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ typedef struct {
/* 0x28 */ u16 equipment; // a mask where each nibble corresponds to a type of equipment `EquipmentType`, and each bit to an owned piece `EquipInv*`
/* 0x2C */ u32 upgrades;
/* 0x30 */ u32 questItems;
/* 0x34 */ u8 dungeonItems[20];
/* 0x48 */ s8 dungeonKeys[19];
/* 0x34 */ u8* dungeonItems;
/* 0x48 */ s8* dungeonKeys;
/* 0x5B */ s8 defenseHearts;
/* 0x5C */ s16 gsTokens;
} Inventory; // size = 0x5E
Expand Down Expand Up @@ -189,7 +189,7 @@ typedef struct {
/* 0x0066 */ s16 savedSceneNum; // Upstream TODO: sceneId
/* 0x0068 */ ItemEquips equips;
/* 0x0074 */ Inventory inventory;
/* 0x00D4 */ SavedSceneFlags sceneFlags[124];
/* 0x00D4 */ SavedSceneFlags* sceneFlags;
/* 0x0E64 */ FaroresWindData fw;
/* 0x0E8C */ char unk_E8C[0x10];
/* 0x0E9C */ s32 gsFlags[6];
Expand Down
2 changes: 1 addition & 1 deletion soh/soh/ActorDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& de
return entry;
}

// Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the return Entry or RetrieveId to get it.
// Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the returned Entry or RetrieveId to get it.
ActorDB::Entry& ActorDB::AddEntry(const ActorDBInit& init) {
Entry& entry = AddEntry(init.name, init.desc, nextFreeId);

Expand Down
5 changes: 3 additions & 2 deletions soh/soh/Enhancements/randomizer/hook_handlers.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <libultraship/bridge.h>
#include "soh/OTRGlobals.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/SceneDB.h"
#include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/custom-message/CustomMessageTypes.h"
#include "soh/Enhancements/item-tables/ItemTableManager.h"
Expand Down Expand Up @@ -835,15 +836,15 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
case VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS:
*should =
LINK_IS_ADULT &&
(gEntranceTable[gSaveContext.entranceIndex].scene == SCENE_TEMPLE_OF_TIME) &&
(EntranceDB::Instance->RetrieveEntry(gSaveContext.entranceIndex).entry.sceneId == SCENE_TEMPLE_OF_TIME) &&
!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) &&
MeetsLACSRequirements();
break;
case VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW:
*should =
!Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL) &&
LINK_IS_ADULT &&
gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_KAKARIKO_VILLAGE &&
(EntranceDB::Instance->RetrieveEntry(gSaveContext.entranceIndex).entry.sceneId == SCENE_KAKARIKO_VILLAGE) &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER);
Expand Down
17 changes: 13 additions & 4 deletions soh/soh/Enhancements/randomizer/logic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <vector>

#include "soh/OTRGlobals.h"
#include "soh/SceneDB.h"
#include "dungeon.h"
#include "context.h"
#include "macros.h"
Expand Down Expand Up @@ -1785,6 +1786,7 @@ namespace Rando {
mSaveContext->equips.equipment = 0;

// Inventory
size_t numScenes = SceneDB::Instance->GetNumEntries();
for (int item = 0; item < ARRAY_COUNT(mSaveContext->inventory.items); item++) {
mSaveContext->inventory.items[item] = ITEM_NONE;
}
Expand All @@ -1794,15 +1796,15 @@ namespace Rando {
mSaveContext->inventory.equipment = 0;
mSaveContext->inventory.upgrades = 0;
mSaveContext->inventory.questItems = 0;
for (int dungeon = 0; dungeon < ARRAY_COUNT(mSaveContext->inventory.dungeonItems); dungeon++) {
for (int dungeon = 0; dungeon < numScenes; dungeon++) {
mSaveContext->inventory.dungeonItems[dungeon] = 0;
}
for (int dungeon = 0; dungeon < ARRAY_COUNT(mSaveContext->inventory.dungeonKeys); dungeon++) {
for (int dungeon = 0; dungeon < numScenes; dungeon++) {
mSaveContext->inventory.dungeonKeys[dungeon] = 0x0;
}
mSaveContext->inventory.defenseHearts = 0;
mSaveContext->inventory.gsTokens = 0;
for (int scene = 0; scene < ARRAY_COUNT(mSaveContext->sceneFlags); scene++) {
for (int scene = 0; scene < numScenes; scene++) {
mSaveContext->sceneFlags[scene].chest = 0;
mSaveContext->sceneFlags[scene].swch = 0;
mSaveContext->sceneFlags[scene].clear = 0;
Expand Down Expand Up @@ -1882,9 +1884,16 @@ namespace Rando {

void Logic::NewSaveContext() {
if (mSaveContext != nullptr && mSaveContext != &gSaveContext) {
free(mSaveContext);
delete[] mSaveContext->inventory.dungeonItems;
delete[] mSaveContext->inventory.dungeonKeys;
delete[] mSaveContext->sceneFlags;
delete mSaveContext;
}
size_t numScenes = SceneDB::Instance->GetNumEntries();
mSaveContext = new SaveContext();
mSaveContext->inventory.dungeonItems = new u8[numScenes];
mSaveContext->inventory.dungeonKeys = new s8[numScenes];
mSaveContext->sceneFlags = new SavedSceneFlags[numScenes];
InitSaveContext();
}

Expand Down
61 changes: 25 additions & 36 deletions soh/soh/Enhancements/randomizer/randomizer_entrance.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "randomizer_grotto.h"
#include "soh/OTRGlobals.h"
#include "soh/SaveManager.h"
#include "soh/SceneDB.h"
#include <string.h>

#include "global.h"
Expand Down Expand Up @@ -46,8 +47,6 @@ static s16 entranceOverrideTable[ENTRANCE_TABLE_SIZE] = {0};
static s16 bossSceneSaveDeathWarps[SHUFFLEABLE_BOSS_COUNT] = {0};
static ActorEntry modifiedLinkActorEntry = {0};

EntranceInfo originalEntranceTable[ENTRANCE_TABLE_SIZE] = {0};

typedef struct {
s16 entryway;
s16 exit;
Expand Down Expand Up @@ -84,15 +83,15 @@ static void Entrance_SeparateOGCFairyFountainExit(void) {
//Overwrite unused entrance 0x03E8 (ENTR_POTION_SHOP_KAKARIKO_1) with values from 0x0340 (ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT) to use it as the
//exit from OGC Great Fairy Fountain -> Castle Grounds
for (size_t i = 0; i < 4; ++i) {
gEntranceTable[ENTR_POTION_SHOP_KAKARIKO_1 + i] = gEntranceTable[ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT + i];
EntranceDB_Copy(ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT + i, ENTR_POTION_SHOP_KAKARIKO_1 + i);
}
}

static void Entrance_SeparateAdultSpawnAndPrelude() {
// Overwrite unused entrance 0x0282 (ENTR_HYRULE_FIELD_10) with values from 0x05F4 (ENTR_TEMPLE_OF_TIME_WARP_PAD) to use it as the
// Adult Spawn index and separate it from Prelude of Light
for (size_t i = 0; i < 4; ++i) {
gEntranceTable[ENTR_HYRULE_FIELD_10 + i] = gEntranceTable[ENTR_TEMPLE_OF_TIME_WARP_PAD + i];
EntranceDB_Copy(ENTR_TEMPLE_OF_TIME_WARP_PAD + i, ENTR_HYRULE_FIELD_10 + i);
}
}

Expand All @@ -101,53 +100,45 @@ static void Entrance_ReplaceChildTempleWarps() {
if (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) {
// Forest Temple
gEntranceTable[ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP] = gEntranceTable[ENTR_SACRED_FOREST_MEADOW_WARP_PAD];
gEntranceTable[ENTR_SACRED_FOREST_MEADOW_3_1] = gEntranceTable[ENTR_SACRED_FOREST_MEADOW_2_1];
EntranceDB_Copy(ENTR_SACRED_FOREST_MEADOW_WARP_PAD, ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP);
EntranceDB_Copy(ENTR_SACRED_FOREST_MEADOW_2_1, ENTR_SACRED_FOREST_MEADOW_3_1);
// Fire Temple
gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP] = gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD];
gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_5_1] = gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_4_1];
EntranceDB_Copy(ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP);
EntranceDB_Copy(ENTR_DEATH_MOUNTAIN_CRATER_4_1, ENTR_DEATH_MOUNTAIN_CRATER_5_1);
// Water Temple
gEntranceTable[ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP] = gEntranceTable[ENTR_LAKE_HYLIA_WARP_PAD];
gEntranceTable[ENTR_LAKE_HYLIA_9_1] = gEntranceTable[ENTR_LAKE_HYLIA_8_1];
EntranceDB_Copy(ENTR_LAKE_HYLIA_WARP_PAD, ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP);
EntranceDB_Copy(ENTR_LAKE_HYLIA_8_1, ENTR_LAKE_HYLIA_9_1);
// Shadow Temple
gEntranceTable[ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP] = gEntranceTable[ENTR_GRAVEYARD_WARP_PAD];
gEntranceTable[ENTR_GRAVEYARD_8_1] = gEntranceTable[ENTR_GRAVEYARD_7_1];
EntranceDB_Copy(ENTR_GRAVEYARD_WARP_PAD, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP);
EntranceDB_Copy(ENTR_GRAVEYARD_7_1, ENTR_GRAVEYARD_8_1);
// Spirit Temple
gEntranceTable[ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP] = gEntranceTable[ENTR_DESERT_COLOSSUS_WARP_PAD];
gEntranceTable[ENTR_DESERT_COLOSSUS_8_1] = gEntranceTable[ENTR_DESERT_COLOSSUS_5_1];
}
}

void Entrance_CopyOriginalEntranceTable(void) {
if (!hasCopiedEntranceTable) {
memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * ENTRANCE_TABLE_SIZE);
hasCopiedEntranceTable = 1;
EntranceDB_Copy(ENTR_DESERT_COLOSSUS_WARP_PAD, ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP);
EntranceDB_Copy(ENTR_DESERT_COLOSSUS_5_1, ENTR_DESERT_COLOSSUS_8_1);
}
}

void Entrance_ResetEntranceTable(void) {
if (hasCopiedEntranceTable && hasModifiedEntranceTable) {
memcpy(gEntranceTable, originalEntranceTable, sizeof(EntranceInfo) * ENTRANCE_TABLE_SIZE);
hasModifiedEntranceTable = 0;
}
EntranceDB_ResetVanillaEntrances();
}

void Entrance_Init(void) {
EntranceOverride* entranceOverrides = Randomizer_GetEntranceOverrides();
s32 index;

Entrance_CopyOriginalEntranceTable();

// Skip Child Stealth if given by settings
if (Randomizer_GetSettingValue(RSK_SKIP_CHILD_STEALTH)) {
gEntranceTable[ENTR_CASTLE_COURTYARD_GUARDS_DAY_0].scene = SCENE_CASTLE_COURTYARD_ZELDA;
gEntranceTable[ENTR_CASTLE_COURTYARD_GUARDS_DAY_0].spawn = 0;
gEntranceTable[ENTR_CASTLE_COURTYARD_GUARDS_DAY_0].field = ENTRANCE_INFO_FIELD(false, false, TRANS_TYPE_FADE_WHITE, TRANS_TYPE_FADE_WHITE);
EntranceDB_Copy(ENTR_CASTLE_COURTYARD_ZELDA_0, ENTR_CASTLE_COURTYARD_GUARDS_DAY_0);
}

// Delete the title card and add a fade in for Hyrule Field from Ocarina of Time cutscene
for (index = ENTR_HYRULE_FIELD_16; index <= ENTR_HYRULE_FIELD_16_3; ++index) {
gEntranceTable[index].field = ENTRANCE_INFO_FIELD(false, false, TRANS_TYPE_FADE_BLACK, TRANS_TYPE_INSTANT);
// Normally modifying a EntranceDBEntry is not safe since it can mess up the internal tables,
// but since we are just changing the cosmetic stuff, it is fine
EntranceDBEntry* entry = EntranceDB_Retrieve(index);
entry->continueBgm = false;
entry->displayTitleCard = false;
entry->endTransition = TRANS_TYPE_FADE_BLACK;
entry->startTransition = TRANS_TYPE_INSTANT;
}

Entrance_SeparateOGCFairyFountainExit();
Expand Down Expand Up @@ -240,9 +231,7 @@ void Entrance_Init(void) {

s16 override = indicesToSilenceBackgroundMusic[j];
for (s16 i = 0; i < 4; i++) {
// Zero out the bit in the field which tells the game to keep playing
// background music for all four scene setups at each index
gEntranceTable[override + i].field &= ~ENTRANCE_INFO_CONTINUE_BGM_FLAG;
EntranceDB_Retrieve(override + i)->continueBgm = false;
}
}
}
Expand Down Expand Up @@ -310,8 +299,8 @@ u32 Entrance_SceneAndSpawnAre(u8 scene, u8 spawn) {
}
}

EntranceInfo currentEntrance = gEntranceTable[entranceIndex];
return currentEntrance.scene == scene && currentEntrance.spawn == spawn;
EntranceDBEntry* entry = EntranceDB_Retrieve(entranceIndex);
return entry->sceneId == scene && entry->spawn == spawn;
}

// Properly respawn the player after a game over, accounting for dungeon entrance randomizer
Expand Down
3 changes: 2 additions & 1 deletion soh/soh/Enhancements/timesaver_hook_handlers.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <libultraship/bridge.h>
#include "soh/OTRGlobals.h"
#include "soh/SceneDB.h"
#include "soh/Enhancements/randomizer/randomizerTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
Expand Down Expand Up @@ -171,7 +172,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
// LACS
u8 meetsLACSRequirements =
LINK_IS_ADULT &&
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) &&
(EntranceDB::Instance->RetrieveEntry(gSaveContext.entranceIndex).entry.sceneId == SCENE_TEMPLE_OF_TIME) &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) &&
!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
Expand Down
5 changes: 3 additions & 2 deletions soh/soh/Enhancements/tts/tts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
#include <spdlog/fmt/fmt.h>

#include "soh/OTRGlobals.h"
#include "soh/SceneDB.h"
#include "message_data_static.h"
#include "overlays/gamestates/ovl_file_choose/file_choose.h"
#include "soh/Enhancements/boss-rush/BossRush.h"
#include "soh/resource/type/SohResourceType.h"

extern "C" {
extern MapData* gMapData;
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
}
Expand Down Expand Up @@ -204,6 +204,7 @@ void RegisterOnKaleidoscopeUpdateHook() {

PauseContext* pauseCtx = &gPlayState->pauseCtx;
Input* input = &gPlayState->state.input[0];
SceneDB::Entry& scene = SceneDB::Instance->RetrieveEntry(gSaveContext.mapIndex);

// Save game prompt
if (pauseCtx->state == 7) {
Expand Down Expand Up @@ -452,7 +453,7 @@ void RegisterOnKaleidoscopeUpdateHook() {

// Cursor is on a dungeon floor position
if (cursorPoint >= 3 && cursorPoint < 11) {
int floorID = gMapData->floorID[gPlayState->interfaceCtx.unk_25A][pauseCtx->dungeonMapSlot - 3];
int floorID = scene.entry.dungeonData.floors[pauseCtx->dungeonMapSlot - 3].id;
// Normalize so F1 == 0, and negative numbers are basement levels
int normalizedFloor = (floorID * -1) + 8;
if (normalizedFloor >= 0) {
Expand Down
3 changes: 3 additions & 0 deletions soh/soh/OTRGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
#include "SohGui.hpp"
#include "ActorDB.h"
#include "SaveManager.h"
#include "SceneDB.h"

#ifdef ENABLE_REMOTE_CONTROL
#include "soh/Network/CrowdControl/CrowdControl.h"
Expand Down Expand Up @@ -1150,6 +1151,8 @@ extern "C" void InitOTR() {
SohGui::SetupGuiElements();
AudioCollection::Instance = new AudioCollection();
ActorDB::Instance = new ActorDB();
SceneDB::Instance = new SceneDB();
EntranceDB::Instance = new EntranceDB();
#ifdef __APPLE__
SpeechSynthesizer::Instance = new DarwinSpeechSynthesizer();
SpeechSynthesizer::Instance->Init();
Expand Down
Loading

0 comments on commit 04df12b

Please sign in to comment.