mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-12-22 16:18:50 -05:00
chore: move rando savefile setup and document flags (#2697)
* remove rando save init from sram * move rando savefile init logic and set more flags * document flags for rando save creation
This commit is contained in:
parent
82b6c48497
commit
059df8187e
@ -365,25 +365,25 @@ typedef enum {
|
||||
* SaveContext.eventChkInf
|
||||
*/
|
||||
|
||||
#define EVENTCHKINF_02 0x02
|
||||
#define EVENTCHKINF_FIRST_SPOKE_TO_MIDO 0x02
|
||||
#define EVENTCHKINF_03 0x03
|
||||
#define EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD 0x04
|
||||
#define EVENTCHKINF_05 0x05
|
||||
#define EVENTCHKINF_DEKU_TREE_OPENED_MOUTH 0x05
|
||||
#define EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD 0x07
|
||||
#define EVENTCHKINF_09 0x09
|
||||
#define EVENTCHKINF_0A 0x0A
|
||||
#define EVENTCHKINF_0B 0x0B
|
||||
#define EVENTCHKINF_0C 0x0C
|
||||
#define EVENTCHKINF_MET_DEKU_TREE 0x0C
|
||||
#define EVENTCHKINF_0F 0x0F
|
||||
#define EVENTCHKINF_10 0x10
|
||||
#define EVENTCHKINF_11 0x11
|
||||
#define EVENTCHKINF_12 0x12
|
||||
#define EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET 0x10
|
||||
#define EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS 0x11
|
||||
#define EVENTCHKINF_OBTAINED_POCKET_EGG 0x12
|
||||
#define EVENTCHKINF_TALON_WOKEN_IN_CASTLE 0x13
|
||||
#define EVENTCHKINF_TALON_RETURNED_FROM_CASTLE 0x14
|
||||
#define EVENTCHKINF_15 0x15
|
||||
#define EVENTCHKINF_16 0x16
|
||||
#define EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH 0x15
|
||||
#define EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON 0x16
|
||||
#define EVENTCHKINF_EPONA_OBTAINED 0x18
|
||||
#define EVENTCHKINF_1B 0x1B
|
||||
#define EVENTCHKINF_RENTED_HORSE_FROM_INGO 0x1B
|
||||
#define EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH 0x1C
|
||||
#define EVENTCHKINF_1D 0x1D
|
||||
#define EVENTCHKINF_1E 0x1E
|
||||
@ -405,7 +405,7 @@ typedef enum {
|
||||
#define EVENTCHKINF_38 0x38
|
||||
#define EVENTCHKINF_39 0x39
|
||||
#define EVENTCHKINF_3A 0x3A
|
||||
#define EVENTCHKINF_3B 0x3B
|
||||
#define EVENTCHKINF_BEGAN_NABOORU_BATTLE 0x3B
|
||||
#define EVENTCHKINF_3C 0x3C
|
||||
|
||||
// 0x40
|
||||
@ -417,21 +417,21 @@ typedef enum {
|
||||
#define EVENTCHKINF_41 0x41
|
||||
#define EVENTCHKINF_42 0x42
|
||||
#define EVENTCHKINF_43 0x43
|
||||
#define EVENTCHKINF_45 0x45
|
||||
#define EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL 0x45
|
||||
#define EVENTCHKINF_48 0x48
|
||||
#define EVENTCHKINF_49 0x49
|
||||
#define EVENTCHKINF_4A 0x4A
|
||||
#define EVENTCHKINF_4B 0x4B
|
||||
#define EVENTCHKINF_OPENED_THE_DOOR_OF_TIME 0x4B
|
||||
#define EVENTCHKINF_4C 0x4C
|
||||
#define EVENTCHKINF_4D 0x4D
|
||||
#define EVENTCHKINF_4E 0x4E
|
||||
#define EVENTCHKINF_4F 0x4F
|
||||
#define EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER 0x4F
|
||||
#define EVENTCHKINF_50 0x50
|
||||
#define EVENTCHKINF_51 0x51
|
||||
#define EVENTCHKINF_52 0x52
|
||||
#define EVENTCHKINF_54 0x54
|
||||
#define EVENTCHKINF_55 0x55
|
||||
#define EVENTCHKINF_59 0x59
|
||||
#define EVENTCHKINF_LEARNED_ZELDAS_LULLABY 0x59
|
||||
#define EVENTCHKINF_5A 0x5A
|
||||
#define EVENTCHKINF_5B 0x5B
|
||||
#define EVENTCHKINF_5C 0x5C
|
||||
@ -449,21 +449,21 @@ typedef enum {
|
||||
|
||||
#define EVENTCHKINF_6E 0x6E
|
||||
#define EVENTCHKINF_6F 0x6F
|
||||
#define EVENTCHKINF_70 0x70
|
||||
#define EVENTCHKINF_71 0x71
|
||||
#define EVENTCHKINF_72 0x72
|
||||
#define EVENTCHKINF_73 0x73
|
||||
#define EVENTCHKINF_74 0x74
|
||||
#define EVENTCHKINF_75 0x75
|
||||
#define EVENTCHKINF_76 0x76
|
||||
#define EVENTCHKINF_77 0x77
|
||||
#define EVENTCHKINF_78 0x78
|
||||
#define EVENTCHKINF_BEGAN_GOHMA_BATTLE 0x70
|
||||
#define EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE 0x71
|
||||
#define EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE 0x72
|
||||
#define EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE 0x73
|
||||
#define EVENTCHKINF_BEGAN_MORPHA_BATTLE 0x74
|
||||
#define EVENTCHKINF_BEGAN_TWINROVA_BATTLE 0x75
|
||||
#define EVENTCHKINF_BEGAN_BARINA_BATTLE 0x76
|
||||
#define EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE 0x77
|
||||
#define EVENTCHKINF_BEGAN_GANONDORF_BATTLE 0x78
|
||||
#define EVENTCHKINF_80 0x80
|
||||
#define EVENTCHKINF_82 0x82
|
||||
#define EVENTCHKINF_8C 0x8C
|
||||
#define EVENTCHKINF_8D 0x8D
|
||||
#define EVENTCHKINF_8E 0x8E
|
||||
#define EVENTCHKINF_8F 0x8F
|
||||
#define EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE 0x8F
|
||||
|
||||
// 0x90-0x93
|
||||
// carpenters freed from the gerudo
|
||||
@ -479,45 +479,45 @@ typedef enum {
|
||||
#define GET_EVENTCHKINF_CARPENTERS_FREE_ALL() \
|
||||
CHECK_FLAG_ALL(gSaveContext.eventChkInf[EVENTCHKINF_CARPENTERS_FREE_INDEX], EVENTCHKINF_CARPENTERS_FREE_MASK_ALL)
|
||||
|
||||
#define EVENTCHKINF_94 0x94
|
||||
#define EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE 0x94
|
||||
#define EVENTCHKINF_95 0x95
|
||||
#define EVENTCHKINF_96 0x96
|
||||
#define EVENTCHKINF_9C 0x9C
|
||||
#define EVENTCHKINF_A0 0xA0
|
||||
#define EVENTCHKINF_A1 0xA1
|
||||
#define EVENTCHKINF_A3 0xA3
|
||||
#define EVENTCHKINF_A4 0xA4
|
||||
#define EVENTCHKINF_A5 0xA5
|
||||
#define EVENTCHKINF_A6 0xA6
|
||||
#define EVENTCHKINF_A7 0xA7
|
||||
#define EVENTCHKINF_A8 0xA8
|
||||
#define EVENTCHKINF_ENTERED_HYRULE_FIELD 0xA0
|
||||
#define EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL 0xA1
|
||||
#define EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE 0xA3
|
||||
#define EVENTCHKINF_ENTERED_ZORAS_DOMAIN 0xA4
|
||||
#define EVENTCHKINF_ENTERED_HYRULE_CASTLE 0xA5
|
||||
#define EVENTCHKINF_ENTERED_GORON_CITY 0xA6
|
||||
#define EVENTCHKINF_ENTERED_TEMPLE_OF_TIME 0xA7
|
||||
#define EVENTCHKINF_ENTERED_DEKU_TREE 0xA8
|
||||
#define EVENTCHKINF_A9 0xA9
|
||||
#define EVENTCHKINF_AA 0xAA
|
||||
#define EVENTCHKINF_AC 0xAC
|
||||
#define EVENTCHKINF_AD 0xAD
|
||||
#define EVENTCHKINF_B0 0xB0
|
||||
#define EVENTCHKINF_B1 0xB1
|
||||
#define EVENTCHKINF_B2 0xB2
|
||||
#define EVENTCHKINF_B3 0xB3
|
||||
#define EVENTCHKINF_B4 0xB4
|
||||
#define EVENTCHKINF_B5 0xB5
|
||||
#define EVENTCHKINF_B6 0xB6
|
||||
#define EVENTCHKINF_B7 0xB7
|
||||
#define EVENTCHKINF_B8 0xB8
|
||||
#define EVENTCHKINF_B9 0xB9
|
||||
#define EVENTCHKINF_BA 0xBA
|
||||
#define EVENTCHKINF_ENTERED_DODONGOS_CAVERN 0xB0
|
||||
#define EVENTCHKINF_ENTERED_LAKE_HYLIA 0xB1
|
||||
#define EVENTCHKINF_ENTERED_GERUDO_VALLEY 0xB2
|
||||
#define EVENTCHKINF_ENTERED_GERUDOS_FORTRESS 0xB3
|
||||
#define EVENTCHKINF_ENTERED_LON_LON_RANCH 0xB4
|
||||
#define EVENTCHKINF_ENTERED_JABU_JABUS_BELLY 0xB5
|
||||
#define EVENTCHKINF_ENTERED_GRAVEYARD 0xB6
|
||||
#define EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN 0xB7
|
||||
#define EVENTCHKINF_ENTERED_DESERT_COLOSSUS 0xB8
|
||||
#define EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER 0xB9
|
||||
#define EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR 0xBA
|
||||
#define EVENTCHKINF_BB 0xBB
|
||||
#define EVENTCHKINF_BC 0xBC
|
||||
#define EVENTCHKINF_BD 0xBD
|
||||
#define EVENTCHKINF_BE 0xBE
|
||||
#define EVENTCHKINF_BF 0xBF
|
||||
#define EVENTCHKINF_C0 0xC0
|
||||
#define EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA 0xC0
|
||||
#define EVENTCHKINF_C1 0xC1
|
||||
#define EVENTCHKINF_C3 0xC3
|
||||
#define EVENTCHKINF_C4 0xC4
|
||||
#define EVENTCHKINF_C5 0xC5
|
||||
#define EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS 0xC4
|
||||
#define EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL 0xC5
|
||||
#define EVENTCHKINF_C6 0xC6
|
||||
#define EVENTCHKINF_C7 0xC7
|
||||
#define EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO 0xC7
|
||||
#define EVENTCHKINF_C8 0xC8
|
||||
#define EVENTCHKINF_C9 0xC9
|
||||
|
||||
@ -617,7 +617,7 @@ typedef enum {
|
||||
* SaveContext.infTable
|
||||
*/
|
||||
|
||||
#define INFTABLE_00 0x00
|
||||
#define INFTABLE_GREETED_BY_SARIA 0x00
|
||||
#define INFTABLE_01 0x01
|
||||
#define INFTABLE_03 0x03
|
||||
#define INFTABLE_05 0x05
|
||||
@ -646,24 +646,24 @@ typedef enum {
|
||||
#define INFTABLE_6A 0x6A
|
||||
#define INFTABLE_6C 0x6C
|
||||
#define INFTABLE_71 0x71
|
||||
#define INFTABLE_76 0x76
|
||||
#define INFTABLE_77 0x77
|
||||
#define INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD 0x76
|
||||
#define INFTABLE_GATE_GUARD_PUT_ON_KEATON_MASK 0x77
|
||||
#define INFTABLE_TALKED_TO_TALON_IN_RANCH_HOUSE 0x7E
|
||||
#define INFTABLE_84 0x84
|
||||
#define INFTABLE_85 0x85
|
||||
#define INFTABLE_8B 0x8B
|
||||
#define INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET 0x84
|
||||
#define INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU 0x85
|
||||
#define INFTABLE_ENTERED_HYRULE_CASTLE 0x8B
|
||||
#define INFTABLE_8C 0x8C
|
||||
#define INFTABLE_8D 0x8D
|
||||
#define INFTABLE_8E 0x8E
|
||||
#define INFTABLE_94 0x94
|
||||
#define INFTABLE_97 0x97
|
||||
#define INFTABLE_9A 0x9A
|
||||
#define INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT 0x9A
|
||||
#define INFTABLE_A2 0xA2
|
||||
#define INFTABLE_AB 0xAB
|
||||
#define INFTABLE_B0 0xB0
|
||||
#define INFTABLE_B1 0xB1
|
||||
#define INFTABLE_B4 0xB4
|
||||
#define INFTABLE_B6 0xB6
|
||||
#define INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET 0xB6
|
||||
#define INFTABLE_B7 0xB7
|
||||
#define INFTABLE_B8 0xB8
|
||||
#define INFTABLE_B9 0xB9
|
||||
@ -705,7 +705,7 @@ typedef enum {
|
||||
#define INFTABLE_SPOKE_TO_GORON_LINK 0x10E
|
||||
#define INFTABLE_10F 0x10F
|
||||
#define INFTABLE_113 0x113
|
||||
#define INFTABLE_11A 0x11A
|
||||
#define INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE 0x11A
|
||||
#define INFTABLE_11E 0x11E
|
||||
#define INFTABLE_124 0x124
|
||||
#define INFTABLE_129 0x129
|
||||
@ -713,10 +713,10 @@ typedef enum {
|
||||
#define INFTABLE_138 0x138
|
||||
#define INFTABLE_139 0x139
|
||||
#define INFTABLE_140 0x140
|
||||
#define INFTABLE_141 0x141
|
||||
#define INFTABLE_142 0x142
|
||||
#define INFTABLE_RUTO_IN_JJ_MEET_RUTO 0x141
|
||||
#define INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME 0x142
|
||||
#define INFTABLE_143 0x143
|
||||
#define INFTABLE_144 0x144
|
||||
#define INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE 0x144
|
||||
#define INFTABLE_145 0x145
|
||||
#define INFTABLE_146 0x146
|
||||
#define INFTABLE_147 0x147
|
||||
@ -739,7 +739,7 @@ typedef enum {
|
||||
#define INFTABLE_191 0x191
|
||||
#define INFTABLE_192 0x192
|
||||
#define INFTABLE_193 0x193
|
||||
#define INFTABLE_195 0x195
|
||||
#define INFTABLE_SPOKE_TO_KAEPORA_IN_LAKE_HYLIA 0x195
|
||||
#define INFTABLE_196 0x196
|
||||
#define INFTABLE_197 0x197
|
||||
#define INFTABLE_198 0x198
|
||||
|
441
soh/soh/Enhancements/randomizer/savefile.cpp
Normal file
441
soh/soh/Enhancements/randomizer/savefile.cpp
Normal file
@ -0,0 +1,441 @@
|
||||
#include "savefile.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
|
||||
extern "C" {
|
||||
#include <z64.h>
|
||||
#include "variables.h"
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
|
||||
uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum);
|
||||
uint8_t Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
|
||||
GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||
}
|
||||
|
||||
void StartingItemGive(GetItemEntry getItemEntry) {
|
||||
if (getItemEntry.modIndex == MOD_NONE) {
|
||||
if (getItemEntry.getItemId == GI_SWORD_BGS) {
|
||||
gSaveContext.bgsFlag = true;
|
||||
}
|
||||
Item_Give(NULL, getItemEntry.itemId);
|
||||
} else if (getItemEntry.modIndex == MOD_RANDOMIZER) {
|
||||
if (getItemEntry.getItemId == RG_ICE_TRAP) {
|
||||
gSaveContext.pendingIceTrapCount++;
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnItemReceive>(getItemEntry);
|
||||
} else {
|
||||
Randomizer_Item_Give(NULL, getItemEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RANDOTODO replace most of these GiveLink functions with calls to
|
||||
// Item_Give in z_parameter, we'll need to update Item_Give to ensure
|
||||
// nothing breaks when calling it without a valid play first
|
||||
void GiveLinkRupees(int numOfRupees) {
|
||||
int maxRupeeCount;
|
||||
if (CUR_UPG_VALUE(UPG_WALLET) == 0) {
|
||||
maxRupeeCount = 99;
|
||||
} else if (CUR_UPG_VALUE(UPG_WALLET) == 1) {
|
||||
maxRupeeCount = 200;
|
||||
} else if (CUR_UPG_VALUE(UPG_WALLET) == 2) {
|
||||
maxRupeeCount = 500;
|
||||
}
|
||||
|
||||
int newRupeeCount = gSaveContext.rupees;
|
||||
newRupeeCount += numOfRupees;
|
||||
|
||||
if (newRupeeCount > maxRupeeCount) {
|
||||
gSaveContext.rupees = maxRupeeCount;
|
||||
} else {
|
||||
gSaveContext.rupees = newRupeeCount;
|
||||
}
|
||||
}
|
||||
|
||||
void GiveLinkDekuSticks(int howManySticks) {
|
||||
int maxStickCount;
|
||||
if (CUR_UPG_VALUE(UPG_STICKS) == 0) {
|
||||
INV_CONTENT(ITEM_STICK) = ITEM_STICK;
|
||||
Inventory_ChangeUpgrade(UPG_STICKS, 1);
|
||||
maxStickCount = 10;
|
||||
} else if (CUR_UPG_VALUE(UPG_STICKS) == 1) {
|
||||
maxStickCount = 10;
|
||||
} else if (CUR_UPG_VALUE(UPG_STICKS) == 2) {
|
||||
maxStickCount = 20;
|
||||
} else if (CUR_UPG_VALUE(UPG_STICKS) == 3) {
|
||||
maxStickCount = 30;
|
||||
}
|
||||
|
||||
if ((AMMO(ITEM_STICK) + howManySticks) > maxStickCount) {
|
||||
AMMO(ITEM_STICK) = maxStickCount;
|
||||
} else {
|
||||
AMMO(ITEM_STICK) += howManySticks;
|
||||
}
|
||||
}
|
||||
|
||||
void GiveLinkDekuNuts(int howManyNuts) {
|
||||
int maxNutCount;
|
||||
if (CUR_UPG_VALUE(UPG_NUTS) == 0) {
|
||||
INV_CONTENT(ITEM_NUT) = ITEM_NUT;
|
||||
Inventory_ChangeUpgrade(UPG_NUTS, 1);
|
||||
maxNutCount = 20;
|
||||
} else if (CUR_UPG_VALUE(UPG_NUTS) == 1) {
|
||||
maxNutCount = 20;
|
||||
} else if (CUR_UPG_VALUE(UPG_NUTS) == 2) {
|
||||
maxNutCount = 30;
|
||||
} else if (CUR_UPG_VALUE(UPG_NUTS) == 3) {
|
||||
maxNutCount = 40;
|
||||
}
|
||||
|
||||
if ((AMMO(ITEM_NUT) + howManyNuts) > maxNutCount) {
|
||||
AMMO(ITEM_NUT) = maxNutCount;
|
||||
} else {
|
||||
AMMO(ITEM_NUT) += howManyNuts;
|
||||
}
|
||||
}
|
||||
|
||||
void GiveLinksPocketItem() {
|
||||
if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING) {
|
||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, (GetItemID)RG_NONE);
|
||||
StartingItemGive(getItemEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void SetStartingItems() {
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD))
|
||||
Item_Give(NULL, ITEM_SWORD_KOKIRI);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD))
|
||||
Item_Give(NULL, ITEM_SHIELD_DEKU);
|
||||
|
||||
// Songs
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_ZELDAS_LULLABY))
|
||||
Item_Give(NULL, ITEM_SONG_LULLABY);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_EPONAS_SONG))
|
||||
Item_Give(NULL, ITEM_SONG_EPONA);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SARIAS_SONG))
|
||||
Item_Give(NULL, ITEM_SONG_SARIA);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SUNS_SONG))
|
||||
Item_Give(NULL, ITEM_SONG_SUN);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SONG_OF_TIME))
|
||||
Item_Give(NULL, ITEM_SONG_TIME);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SONG_OF_STORMS))
|
||||
Item_Give(NULL, ITEM_SONG_STORMS);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_MINUET_OF_FOREST))
|
||||
Item_Give(NULL, ITEM_SONG_MINUET);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_BOLERO_OF_FIRE))
|
||||
Item_Give(NULL, ITEM_SONG_BOLERO);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SERENADE_OF_WATER))
|
||||
Item_Give(NULL, ITEM_SONG_SERENADE);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_REQUIEM_OF_SPIRIT))
|
||||
Item_Give(NULL, ITEM_SONG_REQUIEM);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_NOCTURNE_OF_SHADOW))
|
||||
Item_Give(NULL, ITEM_SONG_NOCTURNE);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_PRELUDE_OF_LIGHT))
|
||||
Item_Give(NULL, ITEM_SONG_PRELUDE);
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SKULLTULA_TOKEN)) {
|
||||
gSaveContext.inventory.questItems |= gBitFlags[QUEST_SKULL_TOKEN];
|
||||
gSaveContext.inventory.gsTokens = Randomizer_GetSettingValue(RSK_STARTING_SKULLTULA_TOKEN);
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) {
|
||||
INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY;
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_CONSUMABLES)) {
|
||||
GiveLinkDekuSticks(10);
|
||||
GiveLinkDekuNuts(20);
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_FULL_WALLETS)) {
|
||||
GiveLinkRupees(9001);
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
uint32_t mapBitMask = 1 << 1;
|
||||
uint32_t compassBitMask = 1 << 2;
|
||||
uint32_t startingDungeonItemsBitMask = mapBitMask | compassBitMask;
|
||||
for (int scene = SCENE_YDAN; scene <= SCENE_ICE_DOUKUTO; scene++) {
|
||||
gSaveContext.inventory.dungeonItems[scene] |= startingDungeonItemsBitMask;
|
||||
}
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_BMORI1] = FOREST_TEMPLE_SMALL_KEY_MAX; // Forest
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_BMORI1] = FOREST_TEMPLE_SMALL_KEY_MAX; // Forest
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_HIDAN] = FIRE_TEMPLE_SMALL_KEY_MAX; // Fire
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_HIDAN] = FIRE_TEMPLE_SMALL_KEY_MAX; // Fire
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_MIZUSIN] = WATER_TEMPLE_SMALL_KEY_MAX; // Water
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_MIZUSIN] = WATER_TEMPLE_SMALL_KEY_MAX; // Water
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = SPIRIT_TEMPLE_SMALL_KEY_MAX; // Spirit
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_JYASINZOU] = SPIRIT_TEMPLE_SMALL_KEY_MAX; // Spirit
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_HAKADAN] = SHADOW_TEMPLE_SMALL_KEY_MAX; // Shadow
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_HAKADAN] = SHADOW_TEMPLE_SMALL_KEY_MAX; // Shadow
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_HAKADANCH] = BOTTOM_OF_THE_WELL_SMALL_KEY_MAX; // BotW
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_HAKADANCH] = BOTTOM_OF_THE_WELL_SMALL_KEY_MAX; // BotW
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_MEN] = GERUDO_TRAINING_GROUNDS_SMALL_KEY_MAX; // GTG
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_MEN] = GERUDO_TRAINING_GROUNDS_SMALL_KEY_MAX; // GTG
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_GANONTIKA] = GANONS_CASTLE_SMALL_KEY_MAX; // Ganon
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_GANONTIKA] = GANONS_CASTLE_SMALL_KEY_MAX; // Ganon
|
||||
} else if (Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_VANILLA) {
|
||||
// Logic cannot handle vanilla key layout in some dungeons
|
||||
// this is because vanilla expects the dungeon major item to be
|
||||
// locked behind the keys, which is not always true in rando.
|
||||
// We can resolve this by starting with some extra keys
|
||||
if (ResourceMgr_IsSceneMasterQuest(SCENE_JYASINZOU)) {
|
||||
// MQ Spirit needs 3 keys
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = 3;
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_JYASINZOU] = 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
gSaveContext.inventory.dungeonItems[SCENE_BMORI1] |= 1; // Forest
|
||||
gSaveContext.inventory.dungeonItems[SCENE_HIDAN] |= 1; // Fire
|
||||
gSaveContext.inventory.dungeonItems[SCENE_MIZUSIN] |= 1; // Water
|
||||
gSaveContext.inventory.dungeonItems[SCENE_JYASINZOU] |= 1; // Spirit
|
||||
gSaveContext.inventory.dungeonItems[SCENE_HAKADAN] |= 1; // Shadow
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == RO_GANON_BOSS_KEY_STARTWITH) {
|
||||
gSaveContext.inventory.dungeonItems[SCENE_GANON] |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void Randomizer_InitSaveFile() {
|
||||
// Sets all rando flags to false
|
||||
for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) {
|
||||
gSaveContext.randomizerInf[i] = 0;
|
||||
}
|
||||
|
||||
gSaveContext.cutsceneIndex = 0; // no intro cutscene
|
||||
// Starts pending ice traps out at 0 before potentially incrementing them down the line.
|
||||
gSaveContext.pendingIceTrapCount = 0;
|
||||
|
||||
// Set Cutscene flags and texts to skip them
|
||||
Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_FIRST_SPOKE_TO_MIDO);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
|
||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_KAEPORA_IN_LAKE_HYLIA);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO);
|
||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE);
|
||||
|
||||
Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON);
|
||||
Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU);
|
||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT);
|
||||
|
||||
// Ruto already met in jabu and spawns down the hole immediately
|
||||
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO);
|
||||
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME);
|
||||
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE);
|
||||
|
||||
// Skip cutscenes before Nabooru fight
|
||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA);
|
||||
|
||||
// Skip boss cutscenes
|
||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE);
|
||||
|
||||
// Entered areas
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_FIELD);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_DOMAIN);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_CASTLE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GORON_CITY);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_TEMPLE_OF_TIME);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEKU_TREE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LAKE_HYLIA);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDO_VALLEY);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDOS_FORTRESS);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LON_LON_RANCH);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_JABU_JABUS_BELLY);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GRAVEYARD);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DESERT_COLOSSUS);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR);
|
||||
Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE);
|
||||
|
||||
// skip the z target talk instructions by the kokiri shop
|
||||
gSaveContext.sceneFlags[SCENE_SPOT04].swch |= (1 << 0x1F);
|
||||
|
||||
// Go away ruto (water temple first cutscene)
|
||||
gSaveContext.sceneFlags[SCENE_MIZUSIN].swch |= (1 << 0x10);
|
||||
|
||||
// no more kaepora
|
||||
gSaveContext.sceneFlags[SCENE_SPOT00].swch |= (1 << 0xC); // hyrule field kaepora outside kokiri forest
|
||||
gSaveContext.sceneFlags[SCENE_SPOT00].swch |= (1 << 0xB); // hyrule field kaepora outside lake hylia
|
||||
gSaveContext.sceneFlags[SCENE_SPOT10].swch |= (1 << 0x7); // lost woods kaepora pre-saria
|
||||
gSaveContext.sceneFlags[SCENE_SPOT10].swch |= (1 << 0x8); // lost woods kaepora post-saria
|
||||
gSaveContext.sceneFlags[SCENE_SPOT11].swch |= (1 << 0x1F); // desert colossus kaepora
|
||||
gSaveContext.sceneFlags[SCENE_SPOT15].swch |= (1 << 0x5); // hyrule castle kaepora
|
||||
|
||||
if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) {
|
||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); // Darunia in Fire Temple
|
||||
}
|
||||
|
||||
// Give Link's pocket item
|
||||
GiveLinksPocketItem();
|
||||
|
||||
// shuffle adult trade quest
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
|
||||
gSaveContext.adultTradeItems = 0;
|
||||
}
|
||||
|
||||
int startingAge = Randomizer_GetSettingValue(RSK_STARTING_AGE);
|
||||
switch (startingAge) {
|
||||
case RO_AGE_ADULT: // Adult
|
||||
gSaveContext.linkAge = LINK_AGE_ADULT;
|
||||
gSaveContext.entranceIndex = 0x5F4;
|
||||
gSaveContext.savedSceneNum = SCENE_SPOT20; // Set scene num manually to ToT
|
||||
break;
|
||||
case RO_AGE_CHILD: // Child
|
||||
gSaveContext.linkAge = LINK_AGE_CHILD;
|
||||
gSaveContext.savedSceneNum = -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS)) {
|
||||
// Override the spawn entrance so entrance rando can take control,
|
||||
// and to prevent remember save location from breaking inital spawn
|
||||
gSaveContext.entranceIndex = -1;
|
||||
}
|
||||
|
||||
// If any trials aren't required, set them as completed
|
||||
for (u16 i = RAND_INF_TRIALS_DONE_LIGHT_TRIAL; i <= RAND_INF_TRIALS_DONE_SHADOW_TRIAL; i++) {
|
||||
if (!OTRGlobals::Instance->gRandomizer->IsTrialRequired((RandomizerInf)i)) {
|
||||
Flags_SetRandomizerInf((RandomizerInf)i);
|
||||
}
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) {
|
||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_SONG_FROM_IMPA, (GetItemID)RG_ZELDAS_LULLABY);
|
||||
StartingItemGive(getItemEntry);
|
||||
|
||||
// malon/talon back at ranch
|
||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_CASTLE);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE);
|
||||
|
||||
// Set "Got Zelda's Letter" flag. Also ensures Saria is back at SFM.
|
||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER);
|
||||
|
||||
// Got item from impa
|
||||
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY);
|
||||
|
||||
gSaveContext.sceneFlags[SCENE_SPOT15].swch |= (1 << 0x4); // move milk crates in hyrule castle to moat
|
||||
|
||||
// set this at the end to ensure we always start with the letter
|
||||
// this is for the off chance we got the weird egg from impa (which should never happen)
|
||||
INV_CONTENT(ITEM_LETTER_ZELDA) = ITEM_LETTER_ZELDA;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Open lowest Vanilla Fire Temple locked door (to prevent key logic lockouts)
|
||||
// Not done on keysanity since this lockout is a non issue when Fire keys can be found outside the temple
|
||||
u8 keysanity = Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE ||
|
||||
Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_OVERWORLD ||
|
||||
Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANY_DUNGEON;
|
||||
if (!ResourceMgr_IsSceneMasterQuest(SCENE_HIDAN) && !keysanity) {
|
||||
gSaveContext.sceneFlags[SCENE_HIDAN].swch |= (1 << 0x17);
|
||||
}
|
||||
|
||||
// Opens locked Water Temple door in vanilla to prevent softlocks
|
||||
// West door on the middle level that leads to the water raising thing
|
||||
// Happens in 3DS rando and N64 rando as well
|
||||
if (!ResourceMgr_IsSceneMasterQuest(SCENE_MIZUSIN)) {
|
||||
gSaveContext.sceneFlags[SCENE_MIZUSIN].swch |= (1 << 0x15);
|
||||
}
|
||||
|
||||
int openForest = Randomizer_GetSettingValue(RSK_FOREST);
|
||||
switch (openForest) {
|
||||
case RO_FOREST_OPEN:
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
|
||||
// Fallthrough
|
||||
case RO_FOREST_CLOSED_DEKU:
|
||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
|
||||
break;
|
||||
}
|
||||
|
||||
int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME);
|
||||
switch (doorOfTime) {
|
||||
case RO_DOOROFTIME_OPEN:
|
||||
Flags_SetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_KAK_GATE) == RO_KAK_GATE_OPEN) {
|
||||
Flags_SetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD);
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_FAST ||
|
||||
Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_OPEN) {
|
||||
Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(1));
|
||||
Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(2));
|
||||
Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(3));
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x02); // heard yells and unlocked doors
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x03);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x04);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x06);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x07);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x08);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x10);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x12);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x13);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].collect |= (1 << 0x0A); // picked up keys
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].collect |= (1 << 0x0E);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].collect |= (1 << 0x0F);
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_OPEN) {
|
||||
Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(0));
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x01); // heard yell and unlocked door
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x05);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].swch |= (1 << 0x11);
|
||||
gSaveContext.sceneFlags[SCENE_GERUDOWAY].collect |= (1 << 0x0C); // picked up key
|
||||
|
||||
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
|
||||
Item_Give(NULL, ITEM_GERUDO_CARD);
|
||||
}
|
||||
}
|
||||
|
||||
// complete mask quest
|
||||
if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) {
|
||||
Flags_SetInfTable(INFTABLE_GATE_GUARD_PUT_ON_KEATON_MASK);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE);
|
||||
gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask
|
||||
gSaveContext.itemGetInf[3] |= 0x200; // Sold Skull Mask
|
||||
gSaveContext.itemGetInf[3] |= 0x400; // Sold Spooky Mask
|
||||
gSaveContext.itemGetInf[3] |= 0x800; // bunny hood related
|
||||
gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth
|
||||
}
|
||||
|
||||
SetStartingItems();
|
||||
}
|
14
soh/soh/Enhancements/randomizer/savefile.h
Normal file
14
soh/soh/Enhancements/randomizer/savefile.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef RANDOSAVEFILE_H
|
||||
#define RANDOSAVEFILE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void Randomizer_InitSaveFile();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -2,10 +2,8 @@
|
||||
#include "vt.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <soh/Enhancements/randomizer/randomizerTypes.h>
|
||||
#include <soh/Enhancements/randomizer/randomizer_inf.h>
|
||||
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
||||
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
||||
#include "soh/Enhancements/randomizer/savefile.h"
|
||||
|
||||
#define NUM_DUNGEONS 8
|
||||
#define NUM_COWS 10
|
||||
@ -31,91 +29,6 @@ void Sram_InitDebugSave(void) {
|
||||
Save_InitFile(true);
|
||||
}
|
||||
|
||||
// RANDOTODO replace most of these GiveLink functions with calls to
|
||||
// Item_Give in z_parameter, we'll need to update Item_Give to ensure
|
||||
// nothing breaks when calling it without a valid play first
|
||||
void GiveLinkRupees(int numOfRupees) {
|
||||
int maxRupeeCount;
|
||||
if (CUR_UPG_VALUE(UPG_WALLET) == 0) {
|
||||
maxRupeeCount = 99;
|
||||
} else if (CUR_UPG_VALUE(UPG_WALLET) == 1) {
|
||||
maxRupeeCount = 200;
|
||||
} else if (CUR_UPG_VALUE(UPG_WALLET) == 2) {
|
||||
maxRupeeCount = 500;
|
||||
}
|
||||
|
||||
int newRupeeCount = gSaveContext.rupees;
|
||||
newRupeeCount += numOfRupees;
|
||||
|
||||
if (newRupeeCount > maxRupeeCount) {
|
||||
gSaveContext.rupees = maxRupeeCount;
|
||||
} else {
|
||||
gSaveContext.rupees = newRupeeCount;
|
||||
}
|
||||
}
|
||||
|
||||
void GiveLinkDekuSticks(int howManySticks) {
|
||||
int maxStickCount;
|
||||
if (CUR_UPG_VALUE(UPG_STICKS) == 0) {
|
||||
INV_CONTENT(ITEM_STICK) = ITEM_STICK;
|
||||
Inventory_ChangeUpgrade(UPG_STICKS, 1);
|
||||
maxStickCount = 10;
|
||||
} else if (CUR_UPG_VALUE(UPG_STICKS) == 1) {
|
||||
maxStickCount = 10;
|
||||
} else if (CUR_UPG_VALUE(UPG_STICKS) == 2) {
|
||||
maxStickCount = 20;
|
||||
} else if (CUR_UPG_VALUE(UPG_STICKS) == 3) {
|
||||
maxStickCount = 30;
|
||||
}
|
||||
|
||||
if ((AMMO(ITEM_STICK) + howManySticks) > maxStickCount) {
|
||||
AMMO(ITEM_STICK) = maxStickCount;
|
||||
} else {
|
||||
AMMO(ITEM_STICK) += howManySticks;
|
||||
}
|
||||
}
|
||||
|
||||
void GiveLinkDekuNuts(int howManyNuts) {
|
||||
int maxNutCount;
|
||||
if (CUR_UPG_VALUE(UPG_NUTS) == 0) {
|
||||
INV_CONTENT(ITEM_NUT) = ITEM_NUT;
|
||||
Inventory_ChangeUpgrade(UPG_NUTS, 1);
|
||||
maxNutCount = 20;
|
||||
} else if (CUR_UPG_VALUE(UPG_NUTS) == 1) {
|
||||
maxNutCount = 20;
|
||||
} else if (CUR_UPG_VALUE(UPG_NUTS) == 2) {
|
||||
maxNutCount = 30;
|
||||
} else if (CUR_UPG_VALUE(UPG_NUTS) == 3) {
|
||||
maxNutCount = 40;
|
||||
}
|
||||
|
||||
if ((AMMO(ITEM_NUT) + howManyNuts) > maxNutCount) {
|
||||
AMMO(ITEM_NUT) = maxNutCount;
|
||||
} else {
|
||||
AMMO(ITEM_NUT) += howManyNuts;
|
||||
}
|
||||
}
|
||||
|
||||
void GiveLinksPocketItem() {
|
||||
if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING) {
|
||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE);
|
||||
|
||||
if (getItemEntry.modIndex == MOD_NONE) {
|
||||
if (getItemEntry.getItemId == GI_SWORD_BGS) {
|
||||
gSaveContext.bgsFlag = true;
|
||||
}
|
||||
Item_Give(NULL, getItemEntry.itemId);
|
||||
} else if (getItemEntry.modIndex == MOD_RANDOMIZER) {
|
||||
if (getItemEntry.getItemId == RG_ICE_TRAP) {
|
||||
gSaveContext.pendingIceTrapCount++;
|
||||
GameInteractor_ExecuteOnItemReceiveHooks(getItemEntry);
|
||||
} else {
|
||||
Randomizer_Item_Give(NULL, getItemEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy save currently on the buffer to Save Context and complete various tasks to open the save.
|
||||
* This includes:
|
||||
@ -305,299 +218,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
||||
fileChooseCtx->n64ddFlag = 1;
|
||||
gSaveContext.n64ddFlag = 1;
|
||||
|
||||
// Sets all rando flags to false
|
||||
for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) {
|
||||
gSaveContext.randomizerInf[i] = 0;
|
||||
}
|
||||
|
||||
// If any trials aren't required, set them as completed
|
||||
for (u16 i = RAND_INF_TRIALS_DONE_LIGHT_TRIAL; i <= RAND_INF_TRIALS_DONE_SHADOW_TRIAL; i++) {
|
||||
if (!Randomizer_IsTrialRequired(i)) {
|
||||
Flags_SetRandomizerInf(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Set Cutscene flags to skip them
|
||||
gSaveContext.eventChkInf[0xC] |= 0x10; // returned to tot with medallions
|
||||
gSaveContext.eventChkInf[0xC] |= 0x20; //sheik at tot pedestal
|
||||
gSaveContext.eventChkInf[4] |= 0x20; // master sword pulled
|
||||
gSaveContext.eventChkInf[4] |= 0x8000; // entered master sword chamber
|
||||
gSaveContext.infTable[0] |= 1;
|
||||
if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) {
|
||||
gSaveContext.infTable[17] |= 0x400; // Darunia in Fire Temple
|
||||
}
|
||||
gSaveContext.cutsceneIndex = 0;
|
||||
Flags_SetEventChkInf(5);
|
||||
|
||||
// Skip boss cutscenes
|
||||
gSaveContext.eventChkInf[7] |= 1; // gohma
|
||||
gSaveContext.eventChkInf[7] |= 2; // dodongo
|
||||
gSaveContext.eventChkInf[7] |= 4; // phantom ganon
|
||||
gSaveContext.eventChkInf[7] |= 8; // volvagia
|
||||
gSaveContext.eventChkInf[7] |= 0x10; // morpha
|
||||
gSaveContext.eventChkInf[7] |= 0x20; // twinrova
|
||||
gSaveContext.eventChkInf[7] |= 0x40; // barinade
|
||||
gSaveContext.eventChkInf[7] |= 0x80; // bongo bongo
|
||||
|
||||
// Skip cutscene before Nabooru fight
|
||||
gSaveContext.eventChkInf[3] |= 0x800;
|
||||
gSaveContext.eventChkInf[12] |= 1;
|
||||
|
||||
// shuffle adult trade quest
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
|
||||
gSaveContext.adultTradeItems = 0;
|
||||
}
|
||||
|
||||
// Starts pending ice traps out at 0 before potentially incrementing them down the line.
|
||||
gSaveContext.pendingIceTrapCount = 0;
|
||||
|
||||
// Give Link's pocket item
|
||||
GiveLinksPocketItem();
|
||||
|
||||
int openForest = Randomizer_GetSettingValue(RSK_FOREST);
|
||||
switch (openForest) {
|
||||
case RO_FOREST_CLOSED:
|
||||
break;
|
||||
case RO_FOREST_CLOSED_DEKU:
|
||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
|
||||
break;
|
||||
case RO_FOREST_OPEN:
|
||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
|
||||
break;
|
||||
}
|
||||
|
||||
int startingAge = Randomizer_GetSettingValue(RSK_STARTING_AGE);
|
||||
switch (startingAge) {
|
||||
case RO_AGE_ADULT: //Adult
|
||||
gSaveContext.linkAge = 0;
|
||||
gSaveContext.entranceIndex = 0x5F4;
|
||||
gSaveContext.savedSceneNum = SCENE_SPOT20; //Set scene num manually to ToT
|
||||
break;
|
||||
case RO_AGE_CHILD: //Child
|
||||
gSaveContext.linkAge = 1;
|
||||
gSaveContext.savedSceneNum = -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS)) {
|
||||
// Override the spawn entrance so entrance rando can take control,
|
||||
// and to prevent remember save location from breaking inital spawn
|
||||
gSaveContext.entranceIndex = -1;
|
||||
}
|
||||
|
||||
int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME);
|
||||
switch (doorOfTime) {
|
||||
case RO_DOOROFTIME_OPEN:
|
||||
gSaveContext.eventChkInf[4] |= 0x800;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_KAK_GATE) == RO_KAK_GATE_OPEN) {
|
||||
gSaveContext.infTable[7] |= 0x40;
|
||||
}
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) Item_Give(NULL, ITEM_SWORD_KOKIRI);
|
||||
if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) Item_Give(NULL, ITEM_SHIELD_DEKU);
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_ZELDAS_LULLABY)) Item_Give(NULL, ITEM_SONG_LULLABY);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_EPONAS_SONG)) Item_Give(NULL, ITEM_SONG_EPONA);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SARIAS_SONG)) Item_Give(NULL, ITEM_SONG_SARIA);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SUNS_SONG)) Item_Give(NULL, ITEM_SONG_SUN);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SONG_OF_TIME)) Item_Give(NULL, ITEM_SONG_TIME);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SONG_OF_STORMS)) Item_Give(NULL, ITEM_SONG_STORMS);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_MINUET_OF_FOREST)) Item_Give(NULL, ITEM_SONG_MINUET);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_BOLERO_OF_FIRE)) Item_Give(NULL, ITEM_SONG_BOLERO);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_SERENADE_OF_WATER)) Item_Give(NULL, ITEM_SONG_SERENADE);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_REQUIEM_OF_SPIRIT)) Item_Give(NULL, ITEM_SONG_REQUIEM);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_NOCTURNE_OF_SHADOW)) Item_Give(NULL, ITEM_SONG_NOCTURNE);
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_PRELUDE_OF_LIGHT)) Item_Give(NULL, ITEM_SONG_PRELUDE);
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_STARTING_SKULLTULA_TOKEN)) {
|
||||
gSaveContext.inventory.questItems |= gBitFlags[QUEST_SKULL_TOKEN];
|
||||
gSaveContext.inventory.gsTokens = Randomizer_GetSettingValue(RSK_STARTING_SKULLTULA_TOKEN);
|
||||
}
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) {
|
||||
INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY;
|
||||
}
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
uint32_t mapBitMask = 1 << 1;
|
||||
uint32_t compassBitMask = 1 << 2;
|
||||
uint32_t startingDungeonItemsBitMask = mapBitMask | compassBitMask;
|
||||
for(int scene = SCENE_YDAN; scene <= SCENE_ICE_DOUKUTO; scene++) {
|
||||
gSaveContext.inventory.dungeonItems[scene] |= startingDungeonItemsBitMask;
|
||||
}
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_STARTING_CONSUMABLES)) {
|
||||
GiveLinkDekuSticks(10);
|
||||
GiveLinkDekuNuts(20);
|
||||
}
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) {
|
||||
GetItemEntry getItem = Randomizer_GetItemFromKnownCheck(RC_SONG_FROM_IMPA, RG_ZELDAS_LULLABY);
|
||||
s32 giid = getItem.getItemId;
|
||||
|
||||
if (getItem.modIndex == MOD_NONE) {
|
||||
if (getItem.getItemId == GI_SWORD_BGS) {
|
||||
gSaveContext.bgsFlag = true;
|
||||
}
|
||||
Item_Give(NULL, getItem.itemId);
|
||||
} else if (getItem.modIndex == MOD_RANDOMIZER) {
|
||||
if (getItem.getItemId == RG_ICE_TRAP) {
|
||||
gSaveContext.pendingIceTrapCount++;
|
||||
GameInteractor_ExecuteOnItemReceiveHooks(getItem);
|
||||
} else {
|
||||
Randomizer_Item_Give(NULL, getItem);
|
||||
}
|
||||
}
|
||||
|
||||
// malon/talon back at ranch
|
||||
gSaveContext.eventChkInf[1] |= (1 << 0);
|
||||
gSaveContext.eventChkInf[1] |= (1 << 2);
|
||||
gSaveContext.eventChkInf[1] |= (1 << 3);
|
||||
gSaveContext.eventChkInf[1] |= (1 << 4);
|
||||
|
||||
// Set "Got Zelda's Letter" flag. Also ensures Saria is back at SFM. TODO: Is this flag used for anything else?
|
||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER);
|
||||
|
||||
// Got item from impa
|
||||
gSaveContext.eventChkInf[5] |= 0x200;
|
||||
|
||||
// set this at the end to ensure we always start with the letter
|
||||
// this is for the off chance we got the weird egg from impa (which should never happen)
|
||||
INV_CONTENT(ITEM_LETTER_ZELDA) = ITEM_LETTER_ZELDA;
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_FULL_WALLETS)) {
|
||||
GiveLinkRupees(9001);
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_BMORI1] = FOREST_TEMPLE_SMALL_KEY_MAX; // Forest
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_BMORI1] = FOREST_TEMPLE_SMALL_KEY_MAX; // Forest
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_HIDAN] = FIRE_TEMPLE_SMALL_KEY_MAX; // Fire
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_HIDAN] = FIRE_TEMPLE_SMALL_KEY_MAX; // Fire
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_MIZUSIN] = WATER_TEMPLE_SMALL_KEY_MAX; // Water
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_MIZUSIN] = WATER_TEMPLE_SMALL_KEY_MAX; // Water
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = SPIRIT_TEMPLE_SMALL_KEY_MAX; // Spirit
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_JYASINZOU] = SPIRIT_TEMPLE_SMALL_KEY_MAX; // Spirit
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_HAKADAN] = SHADOW_TEMPLE_SMALL_KEY_MAX; // Shadow
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_HAKADAN] = SHADOW_TEMPLE_SMALL_KEY_MAX; // Shadow
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_HAKADANCH] = BOTTOM_OF_THE_WELL_SMALL_KEY_MAX; // BotW
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_HAKADANCH] = BOTTOM_OF_THE_WELL_SMALL_KEY_MAX; // BotW
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_MEN] = GERUDO_TRAINING_GROUNDS_SMALL_KEY_MAX; // GTG
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_MEN] = GERUDO_TRAINING_GROUNDS_SMALL_KEY_MAX; // GTG
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_GANONTIKA] = GANONS_CASTLE_SMALL_KEY_MAX; // Ganon
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_GANONTIKA] = GANONS_CASTLE_SMALL_KEY_MAX; // Ganon
|
||||
} else if (Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_VANILLA) {
|
||||
// Logic cannot handle vanilla key layout in some dungeons
|
||||
// this is because vanilla expects the dungeon major item to be
|
||||
// locked behind the keys, which is not always true in rando.
|
||||
// We can resolve this by starting with some extra keys
|
||||
if (ResourceMgr_IsSceneMasterQuest(SCENE_JYASINZOU)) {
|
||||
// MQ Spirit needs 3 keys
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = 3;
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_JYASINZOU] = 3;
|
||||
}
|
||||
}
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
gSaveContext.inventory.dungeonItems[SCENE_BMORI1] |= 1; // Forest
|
||||
gSaveContext.inventory.dungeonItems[SCENE_HIDAN] |= 1; // Fire
|
||||
gSaveContext.inventory.dungeonItems[SCENE_MIZUSIN] |= 1; // Water
|
||||
gSaveContext.inventory.dungeonItems[SCENE_JYASINZOU] |= 1; // Spirit
|
||||
gSaveContext.inventory.dungeonItems[SCENE_HAKADAN] |= 1; // Shadow
|
||||
}
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == RO_GANON_BOSS_KEY_STARTWITH) {
|
||||
gSaveContext.inventory.dungeonItems[SCENE_GANON] |= 1;
|
||||
}
|
||||
|
||||
HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT));
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_SKIP_EPONA_RACE)) {
|
||||
gSaveContext.eventChkInf[1] |= (1 << 8);
|
||||
}
|
||||
|
||||
// skip the z target talk instructions by the kokiri shop
|
||||
gSaveContext.sceneFlags[85].swch |= (1 << 0x1F);
|
||||
|
||||
//Ruto already met in jabu and spawns down the hole immediately
|
||||
gSaveContext.infTable[20] |= 2;
|
||||
gSaveContext.infTable[20] |= 4;
|
||||
|
||||
// Go away ruto (water temple first cutscene)
|
||||
gSaveContext.sceneFlags[SCENE_MIZUSIN].swch |= (1 << 0x10);
|
||||
|
||||
// Open lowest Vanilla Fire Temple locked door (to prevent key logic lockouts)
|
||||
// Not done on keysanity since this lockout is a non issue when Fire keys can be found outside the temple
|
||||
u8 keysanity = Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE ||
|
||||
Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_OVERWORLD ||
|
||||
Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANY_DUNGEON;
|
||||
if (!ResourceMgr_IsSceneMasterQuest(SCENE_HIDAN) && !keysanity) {
|
||||
gSaveContext.sceneFlags[SCENE_HIDAN].swch |= (1 << 0x17);
|
||||
}
|
||||
|
||||
// Opens locked Water Temple door in vanilla to prevent softlocks
|
||||
// West door on the middle level that leads to the water raising thing
|
||||
// Happens in 3DS rando and N64 rando as well
|
||||
if (!ResourceMgr_IsSceneMasterQuest(SCENE_MIZUSIN)) {
|
||||
gSaveContext.sceneFlags[SCENE_MIZUSIN].swch |= (1 << 0x15);
|
||||
}
|
||||
|
||||
// Skip intro cutscene when bombing mud wall in Dodongo's cavern
|
||||
// this also makes the lower jaw render, and the eyes react to explosives
|
||||
Flags_SetEventChkInf(0xB0);
|
||||
|
||||
// skip verbose lake owl, skip to "i'm on my way back to the castle"
|
||||
gSaveContext.infTable[25] |= 0x20;
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_FAST ||
|
||||
Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_OPEN) {
|
||||
gSaveContext.eventChkInf[9] |= 2;
|
||||
gSaveContext.eventChkInf[9] |= 4;
|
||||
gSaveContext.eventChkInf[9] |= 8;
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x02);
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x03);
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x04);
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x06);
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x07);
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x08);
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x10);
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x12);
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x13);
|
||||
gSaveContext.sceneFlags[12].collect |= (1 << 0x0A);
|
||||
gSaveContext.sceneFlags[12].collect |= (1 << 0x0E);
|
||||
gSaveContext.sceneFlags[12].collect |= (1 << 0x0F);
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_OPEN) {
|
||||
gSaveContext.eventChkInf[9] |= 1;
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x01);
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x05);
|
||||
gSaveContext.sceneFlags[12].swch |= (1 << 0x11);
|
||||
gSaveContext.sceneFlags[12].collect |= (1 << 0x0C);
|
||||
|
||||
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
|
||||
Item_Give(NULL, ITEM_GERUDO_CARD);
|
||||
}
|
||||
}
|
||||
|
||||
// complete mask quest
|
||||
if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) {
|
||||
gSaveContext.infTable[7] |= 0x80; // Soldier Wears Keaton Mask
|
||||
gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask
|
||||
gSaveContext.itemGetInf[3] |= 0x200; // Sold Skull Mask
|
||||
gSaveContext.itemGetInf[3] |= 0x400; // Sold Spooky Mask
|
||||
gSaveContext.itemGetInf[3] |= 0x800; // bunny hood related
|
||||
gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth
|
||||
gSaveContext.eventChkInf[8] |= 0x8000; // sold all masks
|
||||
}
|
||||
Randomizer_InitSaveFile();
|
||||
}
|
||||
|
||||
Save_SaveFile();
|
||||
|
Loading…
Reference in New Issue
Block a user