-
Notifications
You must be signed in to change notification settings - Fork 505
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SceneDB [WIP Do not merge] #4460
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are now dynamically sized to support any number of scenes. Fun side effect: all scenes can now have small keys, etc. This was easier and less invasive than restricting it to dungeons and making a mapping from scene id to dungeonItems index. |
||
/* 0x48 */ s8* dungeonKeys; | ||
/* 0x5B */ s8 defenseHearts; | ||
/* 0x5C */ s16 gsTokens; | ||
} Inventory; // size = 0x5E | ||
|
@@ -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]; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
#include <vector> | ||
|
||
#include "soh/OTRGlobals.h" | ||
#include "soh/SceneDB.h" | ||
#include "dungeon.h" | ||
#include "context.h" | ||
#include "macros.h" | ||
|
@@ -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; | ||
} | ||
|
@@ -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; | ||
|
@@ -1882,9 +1884,16 @@ namespace Rando { | |
|
||
void Logic::NewSaveContext() { | ||
if (mSaveContext != nullptr && mSaveContext != &gSaveContext) { | ||
free(mSaveContext); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed free to delete as you should always match malloc/free, new/delete |
||
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(); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
@@ -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; | ||
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note the order is reversed compared to assignment. This is to better match the verbiage of "copy from X to Y". |
||
} | ||
} | ||
|
||
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); | ||
} | ||
} | ||
|
||
|
@@ -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(); | ||
|
@@ -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; | ||
} | ||
} | ||
} | ||
|
@@ -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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have deviated from decomp documentation to add a value to this enum. All dungeons have 8 floors and 0 is used to represent invalid/unused floors. Having an actual enum value saves a lot of static_casts for the scene table.