mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-05-23 22:45:05 -04:00
593 lines
20 KiB
C++
593 lines
20 KiB
C++
#include "tools.h"
|
|
#include "d/actor/d_a_alink.h"
|
|
#include "d/d_com_inf_game.h"
|
|
#include "d/d_item.h"
|
|
#include "d/d_item_data.h"
|
|
#include "dusk/logging.h"
|
|
#include "f_op/f_op_actor_mng.h"
|
|
#include "stages.h"
|
|
#include "verify_item_functions.h"
|
|
|
|
bool playerIsInRoomStage(s32 room, const char* stage)
|
|
{
|
|
// Only check room if it is valid
|
|
// Room numbers are normally stored as int8_t, so the highest positive value is 127
|
|
if ((room < 0) || (room > 127))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (room != dStage_roomControl_c::mStayNo)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Only check stage if it is valid
|
|
if (!stage)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return daAlink_c::checkStageName(stage);
|
|
}
|
|
|
|
void checkTransformFromWolf()
|
|
{
|
|
if (dComIfGs_getTransformStatus())
|
|
{
|
|
daAlink_getAlinkActorClass()->procCoMetamorphoseInit();
|
|
}
|
|
}
|
|
|
|
u8 setNextWarashibeItem()
|
|
{
|
|
static const u8 questItemsList[] = {
|
|
dItemNo_Randomizer_LETTER_e,
|
|
dItemNo_Randomizer_BILL_e,
|
|
dItemNo_Randomizer_WOOD_STATUE_e,
|
|
dItemNo_Randomizer_IRIAS_PENDANT_e,
|
|
dItemNo_Randomizer_HORSE_FLUTE_e
|
|
};
|
|
|
|
u32 listLength = sizeof(questItemsList) / sizeof(questItemsList[0]);
|
|
|
|
u8 newItem = 0xFF; // null by default
|
|
|
|
for (u32 i = 0; i < listLength; i++)
|
|
{
|
|
const u32 item = questItemsList[i];
|
|
const u8 slotItem = dComIfGs_getItem(21, 0);
|
|
if (item == slotItem)
|
|
{
|
|
newItem = item;
|
|
u32 j = i;
|
|
do
|
|
{
|
|
j = (j + 1) % listLength; // Move to next index, wrapping around if needed.
|
|
if (checkItemGet(questItemsList[j], 1))
|
|
{
|
|
newItem = questItemsList[j];
|
|
break;
|
|
}
|
|
} while (j != i);
|
|
|
|
// If the item to switch to is the same as the current item and we don't have the item anymore, null the slot
|
|
if ((newItem == item) && !checkItemGet(item, 1))
|
|
{
|
|
newItem = 0xFF;
|
|
}
|
|
dComIfGs_setItem(21, newItem);
|
|
|
|
break;
|
|
}
|
|
}
|
|
return newItem;
|
|
}
|
|
|
|
void offWarashibeItem(u8 item)
|
|
{
|
|
g_dComIfG_gameInfo.info.getSavedata().getPlayer().getGetItem().offFirstBit(item);
|
|
setNextWarashibeItem();
|
|
}
|
|
|
|
int initCreatePlayerItem(u32 item, u32 flag, const cXyz* pos, int roomNo, const csXyz* angle, const cXyz* scale)
|
|
{
|
|
u32 params = 0xFF0000 | ((flag & 0xFF) << 0x8) | (item & 0xFF);
|
|
return fopAcM_create(539, params, pos, roomNo, angle, scale, -1);
|
|
}
|
|
|
|
int getStageID(const char* stage)
|
|
{
|
|
int loopCount = sizeof(allStages) / sizeof(allStages[0]);
|
|
for (int i = 0; i < loopCount; i++)
|
|
{
|
|
// If stage is NULL, check for current stage
|
|
if (stage == NULL) {
|
|
if (daAlink_c::checkStageName(allStages[i])) return i;
|
|
} else if (strcmp(stage, allStages[i]) == 0) {
|
|
return i;
|
|
}
|
|
}
|
|
// Didn't find the current stage for some reason
|
|
return -1;
|
|
}
|
|
|
|
bool playerIsOnTitleScreen() {
|
|
// Player is either on title screen movie stage (S_MV000) or on title screen map layer 10
|
|
return strcmp(dComIfGp_getStartStageName(), "S_MV000") == 0 ||
|
|
(strcmp(dComIfGp_getStartStageName(), "F_SP102") == 0 && dComIfG_play_c::getLayerNo(0) == 10);
|
|
}
|
|
|
|
u16 getItemMessageID(u8 itemId) {
|
|
// If heart piece, choose from the different heart piece messages
|
|
if (itemId == dItemNo_Randomizer_KAKERA_HEART_e) {
|
|
static u32 const heartPieceMessage[5] = {0x86, 0x9C, 0x9D, 0x9E, 0x9F};
|
|
return heartPieceMessage[dComIfGs_getMaxLife() % 5];
|
|
}
|
|
|
|
return itemId + 0x65;
|
|
}
|
|
|
|
int numCompletedDungeons() {
|
|
int numCompleted{0};
|
|
// Loop through dungeon area node ids
|
|
for (int i = 0x10; i < 0x18; ++i) {
|
|
numCompleted += dComIfGs_isStageBossEnemy(i);
|
|
}
|
|
return numCompleted;
|
|
}
|
|
|
|
int numFusedShadows() {
|
|
int numFusedShadows{0};
|
|
for (int i = 0; i < 3; ++i) {
|
|
numFusedShadows += dComIfGs_isCollectCrystal(i);
|
|
}
|
|
return numFusedShadows;
|
|
}
|
|
|
|
int numMirrorShards() {
|
|
int numMirrorShards{0};
|
|
for (int i = 0; i < 4; ++i) {
|
|
numMirrorShards += dComIfGs_isCollectMirror(i);
|
|
}
|
|
return numMirrorShards;
|
|
}
|
|
|
|
int getTempleKeysFound(int stage) {
|
|
static std::unordered_map<int, std::vector<int>> keyDoorFlags = {
|
|
{0xA, {0x0}},
|
|
{0x10, {0x7, 0xB, 0x2B, 0x3E}},
|
|
{0x11, {0x33, 0x3D, 0x3F}},
|
|
{0x12, {0x23, 0x24, 0x34}},
|
|
{0x13, {0x27, 0x46, 0x4D, 0x5A, 0x5B}},
|
|
{0x14, {0x2B, 0x2C, 0x2F, 0x30}},
|
|
{0x15, {0x1B, 0x1C, 0x1D}},
|
|
{0x16, {0x6}},
|
|
{0x17, {0x6, 0x7, 0x8, 0xB, 0x23, 0x24, 0x25}},
|
|
{0x18, {0x4C, 0x6F, 0x7C}}
|
|
};
|
|
|
|
int count = dComIfGs_getKeyNum(stage);
|
|
|
|
// Add number of unlocked key doors for this dungeon to current key count
|
|
for (auto flag : keyDoorFlags[stage]) {
|
|
if (dComIfGs_isSwitch(stage, flag)) {
|
|
count += 1;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
bool isTempleBigKeyFound(int stage) {
|
|
// The boss key never gets taken away unlike small keys
|
|
return dComIfGs_isDungeonItemBossKey(stage);
|
|
}
|
|
|
|
randomizer::logic::item_pool::ItemPool getSaveItemPool(randomizer::logic::world::World* world) {
|
|
randomizer::logic::item_pool::ItemPool pool{};
|
|
|
|
// Item wheel items
|
|
for (int i = 0; i < MAX_ITEM_SLOTS; ++i) {
|
|
switch (dComIfGs_getItem(i, false)) {
|
|
case dItemNo_Randomizer_HAWK_EYE_e:
|
|
pool.push_back(world->GetItem("Hawkeye", true));
|
|
break;
|
|
case dItemNo_Randomizer_BOOMERANG_e:
|
|
pool.push_back(world->GetItem("Gale Boomerang", true));
|
|
break;
|
|
case dItemNo_Randomizer_SPINNER_e:
|
|
pool.push_back(world->GetItem("Spinner", true));
|
|
break;
|
|
case dItemNo_Randomizer_IRONBALL_e:
|
|
pool.push_back(world->GetItem("Ball and Chain", true));
|
|
break;
|
|
case dItemNo_Randomizer_BOW_e:
|
|
pool.push_back(world->GetItem("Progressive Bow", true));
|
|
break;
|
|
case dItemNo_Randomizer_W_HOOKSHOT_e:
|
|
pool.push_back(world->GetItem("Progressive Clawshot", true));
|
|
[[fallthrough]];
|
|
case dItemNo_Randomizer_HOOKSHOT_e:
|
|
pool.push_back(world->GetItem("Progressive Clawshot", true));
|
|
break;
|
|
case dItemNo_Randomizer_HVY_BOOTS_e:
|
|
pool.push_back(world->GetItem("Iron Boots", true));
|
|
break;
|
|
case dItemNo_Randomizer_COPY_ROD_e:
|
|
pool.push_back(world->GetItem("Progressive Dominion Rod", true));
|
|
// Powered up dominion rod
|
|
if (dComIfGs_isEventBit(0x2580)) {
|
|
pool.push_back(world->GetItem("Progressive Dominion Rod", true));
|
|
}
|
|
break;
|
|
case dItemNo_Randomizer_KANTERA_e:
|
|
pool.push_back(world->GetItem("Lantern", true));
|
|
break;
|
|
case dItemNo_Randomizer_JEWEL_ROD_e:
|
|
case dItemNo_Randomizer_JEWEL_BEE_ROD_e:
|
|
case dItemNo_Randomizer_JEWEL_WORM_ROD_e:
|
|
pool.push_back(world->GetItem("Progressive Fishing Rod", true));
|
|
[[fallthrough]];
|
|
case dItemNo_Randomizer_FISHING_ROD_1_e:
|
|
case dItemNo_Randomizer_BEE_ROD_e:
|
|
case dItemNo_Randomizer_WORM_ROD_e:
|
|
pool.push_back(world->GetItem("Progressive Fishing Rod", true));
|
|
break;
|
|
case dItemNo_Randomizer_PACHINKO_e:
|
|
pool.push_back(world->GetItem("Slingshot", true));
|
|
break;
|
|
case dItemNo_Randomizer_BOMB_BAG_LV1_e:
|
|
case dItemNo_Randomizer_NORMAL_BOMB_e:
|
|
case dItemNo_Randomizer_WATER_BOMB_e:
|
|
case dItemNo_Randomizer_POKE_BOMB_e:
|
|
pool.push_back(world->GetItem("Bomb Bag", true));
|
|
break;
|
|
case dItemNo_Randomizer_RAFRELS_MEMO_e:
|
|
pool.push_back(world->GetItem("Aurus Memo", true));
|
|
break;
|
|
case dItemNo_Randomizer_ASHS_SCRIBBLING_e:
|
|
pool.push_back(world->GetItem("Asheis Sketch", true));
|
|
break;
|
|
case dItemNo_Randomizer_EMPTY_BOTTLE_e:
|
|
case dItemNo_Randomizer_RED_BOTTLE_e:
|
|
case dItemNo_Randomizer_GREEN_BOTTLE_e:
|
|
case dItemNo_Randomizer_BLUE_BOTTLE_e:
|
|
case dItemNo_Randomizer_MILK_BOTTLE_e:
|
|
case dItemNo_Randomizer_HALF_MILK_BOTTLE_e:
|
|
case dItemNo_Randomizer_OIL_BOTTLE_e:
|
|
case dItemNo_Randomizer_WATER_BOTTLE_e:
|
|
case dItemNo_Randomizer_OIL_BOTTLE_2_e:
|
|
case dItemNo_Randomizer_RED_BOTTLE_2_e:
|
|
case dItemNo_Randomizer_UGLY_SOUP_e:
|
|
case dItemNo_Randomizer_HOT_SPRING_e:
|
|
case dItemNo_Randomizer_FAIRY_e:
|
|
case dItemNo_Randomizer_HOT_SPRING_2_e:
|
|
case dItemNo_Randomizer_OIL2_e:
|
|
case dItemNo_Randomizer_OIL_e:
|
|
case dItemNo_Randomizer_FAIRY_DROP_e:
|
|
case dItemNo_Randomizer_DROP_BOTTLE_e:
|
|
case dItemNo_Randomizer_BEE_CHILD_e:
|
|
case dItemNo_Randomizer_CHUCHU_RARE_e:
|
|
case dItemNo_Randomizer_CHUCHU_RED_e:
|
|
case dItemNo_Randomizer_CHUCHU_BLUE_e:
|
|
case dItemNo_Randomizer_CHUCHU_GREEN_e:
|
|
case dItemNo_Randomizer_CHUCHU_YELLOW_e:
|
|
case dItemNo_Randomizer_CHUCHU_PURPLE_e:
|
|
case dItemNo_Randomizer_LV1_SOUP_e:
|
|
case dItemNo_Randomizer_LV2_SOUP_e:
|
|
case dItemNo_Randomizer_LV3_SOUP_e:
|
|
case dItemNo_Randomizer_OIL_BOTTLE3_e:
|
|
case dItemNo_Randomizer_CHUCHU_BLACK_e:
|
|
pool.push_back(world->GetItem("Empty Bottle", true));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Shadow Crystal
|
|
if (dComIfGs_isEventBit(0xD04)) {
|
|
pool.push_back(world->GetItem("Shadow Crystal", true));
|
|
}
|
|
|
|
// Fused Shadows
|
|
for (int i = 0; i < numFusedShadows(); ++i) {
|
|
pool.push_back(world->GetItem("Progressive Fused Shadow", true));
|
|
}
|
|
|
|
// Mirror Shards
|
|
for (int i = 0; i < numMirrorShards(); ++i) {
|
|
pool.push_back(world->GetItem("Progressive Mirror Shard", true));
|
|
}
|
|
|
|
// Poe Souls
|
|
for (int i = 0; i < dComIfGs_getPohSpiritNum(); ++i) {
|
|
pool.push_back(world->GetItem("Poe Soul", true));
|
|
}
|
|
|
|
// Hearts
|
|
for (int i = 0; i < dComIfGs_getMaxLife(); ++i) {
|
|
pool.push_back(world->GetItem("Piece of Heart", true));
|
|
}
|
|
|
|
// Sky Book characters
|
|
for (int i = 0; i < dComIfGs_getAncientDocumentNum(); ++i) {
|
|
pool.push_back(world->GetItem("Progressive Sky Book", true));
|
|
}
|
|
|
|
// Small Keys
|
|
static std::unordered_map<int, std::string> keyRegionItemNameMap = {
|
|
{0xA, "Gerudo Desert Bulblin Camp Key"},
|
|
{0x10, "Forest Temple Small Key"},
|
|
{0x11, "Goron Mines Small Key"},
|
|
{0x12, "Lakebed Temple Small Key"},
|
|
{0x13, "Arbiters Grounds Small Key"},
|
|
{0x14, "Snowpeak Ruins Small Key"},
|
|
{0x15, "Temple of Time Small Key"},
|
|
{0x16, "City in the Sky Small Key"},
|
|
{0x17, "Palace of Twilight Small Key"},
|
|
{0x18, "Hyrule Castle Small Key"},
|
|
};
|
|
for (auto& [stage, keyName] : keyRegionItemNameMap) {
|
|
for (int i = 0; i < getTempleKeysFound(stage); ++i) {
|
|
pool.push_back(world->GetItem(keyName, true));
|
|
}
|
|
}
|
|
|
|
// Gate Keys
|
|
if (haveItem(dItemNo_Randomizer_BOSSRIDER_KEY_e)) {
|
|
pool.push_back(world->GetItem(dItemNo_Randomizer_BOSSRIDER_KEY_e, true));
|
|
}
|
|
|
|
// Big Keys
|
|
static std::unordered_map<int, std::string> bigKeyRegionItemNameMap = {
|
|
{0x10, "Forest Temple Big Key"},
|
|
{0x12, "Lakebed Temple Big Key"},
|
|
{0x13, "Arbiters Grounds Big Key"},
|
|
{0x14, "Snowpeak Ruins Bedroom Key"},
|
|
{0x15, "Temple of Time Big Key"},
|
|
{0x16, "City in the Sky Big Key"},
|
|
{0x17, "Palace of Twilight Big Key"},
|
|
{0x18, "Hyrule Castle Big Key"},
|
|
};
|
|
for (auto& [stage, keyName] : bigKeyRegionItemNameMap) {
|
|
if (isTempleBigKeyFound(stage)) {
|
|
pool.push_back(world->GetItem(keyName, true));
|
|
}
|
|
}
|
|
|
|
// Goron Mines Key Shards
|
|
for (int i = dItemNo_Randomizer_L2_KEY_PIECES1_e; i < dItemNo_Randomizer_L2_KEY_PIECES3_e; ++i) {
|
|
if (haveItem(i)) {
|
|
pool.push_back(world->GetItem("Goron Mines Key Shard", true));
|
|
}
|
|
}
|
|
|
|
// Ordon Pumpkin
|
|
if (haveItem(dItemNo_Randomizer_TOMATO_PUREE_e)) {
|
|
pool.push_back(world->GetItem(dItemNo_Randomizer_TOMATO_PUREE_e, true));
|
|
}
|
|
|
|
// Ordon Cheese
|
|
if (haveItem(dItemNo_Randomizer_TASTE_e)) {
|
|
pool.push_back(world->GetItem(dItemNo_Randomizer_TASTE_e, true));
|
|
}
|
|
|
|
// Golden Bugs
|
|
for (int i = dItemNo_Randomizer_M_BEETLE_e; i < dItemNo_Randomizer_F_MAYFLY_e; ++i) {
|
|
if (haveItem(i)) {
|
|
pool.push_back(world->GetItem(i, true));
|
|
}
|
|
}
|
|
|
|
// Ilia quest items
|
|
for (int i = dItemNo_Randomizer_LETTER_e; i < dItemNo_Randomizer_HORSE_FLUTE_e; ++i) {
|
|
if (haveItem(i)) {
|
|
pool.push_back(world->GetItem(i, true));
|
|
}
|
|
}
|
|
|
|
// Warp Portals
|
|
// Item ids are scattered so we have to explicitly list them all
|
|
static const int portals[] = {
|
|
dItemNo_Randomizer_ORDON_PORTAL_e,
|
|
dItemNo_Randomizer_SOUTH_FARON_PORTAL_e,
|
|
dItemNo_Randomizer_NORTH_FARON_PORTAL_e,
|
|
dItemNo_Randomizer_SACRED_GROVE_PORTAL_e,
|
|
dItemNo_Randomizer_KAKARIKO_GORGE_PORTAL_e,
|
|
dItemNo_Randomizer_KAKARIKO_VILLAGE_PORTAL_e,
|
|
dItemNo_Randomizer_DEATH_MOUNTAIN_PORTAL_e,
|
|
dItemNo_Randomizer_ELDIN_BRIDGE_PORTAL_e,
|
|
dItemNo_Randomizer_CASTLE_TOWN_PORTAL_e,
|
|
dItemNo_Randomizer_UPPER_ZORAS_RIVER_PORTAL_e,
|
|
dItemNo_Randomizer_ZORAS_DOMAIN_PORTAL_e,
|
|
dItemNo_Randomizer_SNOWPEAK_PORTAL_e,
|
|
dItemNo_Randomizer_GERUDO_DESERT_PORTAL_e,
|
|
dItemNo_Randomizer_MIRROR_CHAMBER_PORTAL_e,
|
|
};
|
|
for (auto portal : portals) {
|
|
if (haveItem(portal)) {
|
|
pool.push_back(world->GetItem(portal, true));
|
|
}
|
|
}
|
|
|
|
// Swords
|
|
static const int swords[] = {
|
|
dItemNo_Randomizer_WOOD_STICK_e,
|
|
dItemNo_Randomizer_SWORD_e,
|
|
dItemNo_Randomizer_MASTER_SWORD_e,
|
|
dItemNo_Randomizer_LIGHT_SWORD_e,
|
|
};
|
|
for (auto sword : swords) {
|
|
if (haveItem(sword)) {
|
|
pool.push_back(world->GetItem("Progressive Sword", true));
|
|
}
|
|
}
|
|
|
|
// Other Equipment
|
|
static const int equipment[] = {
|
|
dItemNo_Randomizer_WOOD_SHIELD_e,
|
|
dItemNo_Randomizer_HYLIA_SHIELD_e,
|
|
dItemNo_Randomizer_WEAR_ZORA_e,
|
|
dItemNo_Randomizer_ARMOR_e,
|
|
};
|
|
for (auto item : equipment) {
|
|
if (haveItem(item)) {
|
|
pool.push_back(world->GetItem(item, true));
|
|
}
|
|
}
|
|
|
|
// Hidden Skills
|
|
static const int hiddenSkills[] = {
|
|
dItemNo_Randomizer_ENDING_BLOW_e,
|
|
dItemNo_Randomizer_SHIELD_ATTACK_e,
|
|
dItemNo_Randomizer_BACK_SLICE_e,
|
|
dItemNo_Randomizer_HELM_SPLITTER_e,
|
|
dItemNo_Randomizer_MORTAL_DRAW_e,
|
|
dItemNo_Randomizer_JUMP_STRIKE_e,
|
|
dItemNo_Randomizer_GREAT_SPIN_e,
|
|
};
|
|
for (auto skill : hiddenSkills) {
|
|
if (haveItem(skill)) {
|
|
pool.push_back(world->GetItem("Progressive Hidden Skill", true));
|
|
}
|
|
}
|
|
|
|
// Wallets
|
|
switch (dComIfGs_getWalletSize()) {
|
|
case GIANT_WALLET:
|
|
pool.push_back(world->GetItem("Progressive Wallet", true));
|
|
[[fallthrough]];
|
|
case BIG_WALLET:
|
|
pool.push_back(world->GetItem("Progressive Wallet", true));
|
|
[[fallthrough]];
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return pool;
|
|
}
|
|
|
|
int getStageSaveId(int id) {
|
|
switch (id) {
|
|
case 41: // F_SP00 (Ordon Ranch)
|
|
case 43: // F_SP103 (Ordon Village / Outside Link's House)
|
|
case 44: // F_SP104 (Ordon Spring)
|
|
case 65: // R_SP01 (Ordon House Interiors)
|
|
return 0x0;
|
|
case 66: // R_SP107 (Castle Town Sewers)
|
|
return 0x1;
|
|
case 40: // D_SB10 (Faron Woods Cave)
|
|
case 45: // F_SP108 (Faron Woods)
|
|
case 67: // R_SP108 (Coro's House)
|
|
return 0x2;
|
|
case 46: // F_SP109 (Kakariko Village)
|
|
case 47: // F_SP110 (Death Mountain Trail)
|
|
case 48: // F_SP111 (Kakariko Graveyard)
|
|
case 63: // F_SP128 (Hidden Village)
|
|
case 68: // R_SP109 (Kakariko Interiors)
|
|
case 69: // R_SP110 (Goron Elder's Hall)
|
|
case 72: // R_SP128 (Impaz's House)
|
|
case 75: // R_SP209 (Sanctuary Basement)
|
|
return 0x3;
|
|
case 49: // F_SP112 (Zora's River)
|
|
case 50: // F_SP113 (Zora's Domain)
|
|
case 52: // F_SP115 (Lake Hylia)
|
|
case 61: // F_SP126 (Upper Zora's River)
|
|
case 71: // R_SP127 (Hena's Cabin)
|
|
return 0x4;
|
|
case 56: // F_SP121 (Hyrule Field)
|
|
case 57: // F_SP122 (Outside Castle Town)
|
|
case 58: // F_SP123 (King Bulblin 2)
|
|
case 64: // F_SP200 (Wolf Howling Cutscene Map)
|
|
return 0x6;
|
|
case 54: // F_SP117 (Lost Woods)
|
|
return 0x7;
|
|
case 51: // F_SP114 (Snowpeak Mountain)
|
|
return 0x8;
|
|
case 53: // F_SP116 (Castle Town)
|
|
case 70: // R_SP116 (Telma's Bar / Secret Passage)
|
|
case 73: // R_SP160 (Hyrule Castle Town Interiors)
|
|
case 74: // R_SP161 (STAR Tent)
|
|
return 0x9;
|
|
case 55: // F_SP118 (Bulblin Camp)
|
|
case 59: // F_SP124 (Gerudo Desert)
|
|
case 60: // F_SP125 (Mirror Chamber)
|
|
return 0xA;
|
|
case 62: // F_SP127 (Fishing Pond)
|
|
return 0xB;
|
|
case 6: // D_MN05 (Forest Temple)
|
|
case 7: // D_MN05A (Diababa Arena)
|
|
case 8: // D_MN05B (Ook Arena)
|
|
return 0x10;
|
|
case 3: // D_MN04 (Goron Mines)
|
|
case 4: // D_MN04A (Fyrus Arena)
|
|
case 5: // D_MN04B (Dangoro Arena)
|
|
return 0x11;
|
|
case 0: // D_MN01 (Lakebed Temple)
|
|
case 1: // D_MN01A (Morpheel Arena)
|
|
case 2: // D_MN01B (Deku Toad Arena)
|
|
return 0x12;
|
|
case 24: // D_MN10 (Arbiter's Grounds)
|
|
case 25: // D_MN10A (Stallord Arena)
|
|
case 26: // D_MN10B (Death Sword Arena)
|
|
return 0x13;
|
|
case 27: // D_MN11 (Snowpeak Ruins)
|
|
case 28: // D_MN11A (Blizzeta Arena)
|
|
case 29: // D_MN11B (Darkhammer Arena)
|
|
return 0x14;
|
|
case 9: // D_MN06 (Temple of Time)
|
|
case 10: // D_MN06A (Armogohma Arena)
|
|
case 11: // D_MN06B (Darknut Arena)
|
|
return 0x15;
|
|
case 12: // D_MN07 (City in the Sky)
|
|
case 13: // D_MN07A (Argorok Arena)
|
|
case 14: // D_MN07B (Aeralfos Arena)
|
|
return 0x16;
|
|
case 15: // D_MN08 (Palace of Twilight)
|
|
case 16: // D_MN08A (Palace of Twilight Throne Room)
|
|
case 17: // D_MN08B (Phantom Zant Arena 1)
|
|
case 18: // D_MN08C (Phantom Zant Arena 2)
|
|
case 19: // D_MN08D (Zant Arenas)
|
|
return 0x17;
|
|
case 20: // D_MN09 (Hyrule Castle)
|
|
case 21: // D_MN09A (Hyrule Castle Throne Room)
|
|
case 22: // D_MN09B (Horseback Ganondorf Arena)
|
|
case 23: // D_MN09C (Dark Lord Ganondorf Arena)
|
|
return 0x18;
|
|
case 30: // D_SB00 (Ice Cavern)
|
|
case 31: // D_SB01 (Cave Of Ordeals)
|
|
case 32: // D_SB02 (Kakariko Gorge Cavern)
|
|
return 0x19;
|
|
case 33: // D_SB03 (Lake Hylia Cavern)
|
|
case 34: // D_SB04 (Goron Stockcave)
|
|
return 0x1A;
|
|
case 35: // D_SB05 (Grotto 1)
|
|
case 36: // D_SB06 (Grotto 2)
|
|
case 37: // D_SB07 (Grotto 3)
|
|
case 38: // D_SB08 (Grotto 4)
|
|
case 39: // D_SB09 (Grotto 5)
|
|
return 0x1B;
|
|
case 42: // F_SP102 (Title Screen / King Bulblin 1)
|
|
return 0xFF;
|
|
default:
|
|
DuskLog.warn("Failed to find Save Id for ID: {}" , id);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int getStageSaveId(const char* stage) {
|
|
int id = getStageID(stage);
|
|
return getStageSaveId(id);
|
|
}
|
|
|
|
bool tracker_isEventBit(u16 flag) {
|
|
return g_randomizerState.mTrackerTempEventFlag == flag || dComIfGs_isEventBit(flag);
|
|
}
|
|
|
|
bool tracker_isStageSwitch(int stage, int flag) {
|
|
return dComIfGs_isStageSwitch(stage, flag) ||
|
|
(g_randomizerState.mTrackerTempSwitchFlag.flag == flag &&
|
|
g_randomizerState.mTrackerTempSwitchFlag.stage == stage);
|
|
} |