Enable MQ Dungeons in Randomizer (#1828)

* Refactor GetCheckFromActor, WIP currently broken

* Fixes build errors via forward declarations and emplace vs insert.

* Removes some unnecessary code.

* Fixes non-windows build errors.

* Fixes Deku Scrubs outside of grottos.

* Fixes DMC Deku Scrub Grotto Center

* Fixes Ruto Blue Warp

* Fix issue identifying blue warp rando checks

* Move identifyCow to randomizer.cpp

* Various updates to vanilla check objects

* Identify MQ checks in check object table

* Adjustments to how multimap is used and initialized

* Convert u16 in check object table to s16

* Fix a few issues with MQ checks

* Fix issue with TWO_ACTOR_PARAMS macro

* Fixes some scrubs and cows appearing as identical.

* Fixes known gossip stone issues (ToT, DC)

* Fixes Dampe's Gravedigging tour rcObject

* Fix crash on locations tab

* Enable master quest dungeons in rando

Co-authored-by: Christopher Leggett <chris@leggett.dev>
This commit is contained in:
Garrett Cox 2022-10-21 20:43:37 -05:00 committed by GitHub
parent ef73aa4f8d
commit 1db4e9303e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1197 additions and 2583 deletions

View File

@ -266,7 +266,7 @@ extern GraphicsContext* __gfxCtx;
#define NUM_TRIALS 6
#define NUM_SHOP_ITEMS 64
#define NUM_SCRUBS 35
#define NUM_SCRUBS 46
#define FOREST_TEMPLE_SMALL_KEY_MAX (ResourceMgr_IsSceneMasterQuest(SCENE_BMORI1) ? 6 : 5)
#define FIRE_TEMPLE_SMALL_KEY_MAX (ResourceMgr_IsSceneMasterQuest(SCENE_HIDAN) ? 5 : 8)
#define WATER_TEMPLE_SMALL_KEY_MAX (ResourceMgr_IsSceneMasterQuest(SCENE_MIZUSIN) ? 2 : 6)

View File

@ -350,10 +350,14 @@ typedef enum {
#define DEFINE_ACTOR_UNSET(enum) enum,
#define DEFINE_ACTOR(_0, enum, _2) DEFINE_ACTOR_INTERNAL(_0, enum, _2)
typedef enum {
#ifdef __cplusplus
enum ActorID : int {
#else
enum ActorID {
#endif
#include "tables/actor_table.h"
/* 0x0192 */ ACTOR_ID_MAX // originally "ACTOR_DLF_MAX"
} ActorID;
};
#undef DEFINE_ACTOR
#undef DEFINE_ACTOR_INTERNAL

View File

@ -184,7 +184,7 @@ typedef struct {
char ganonHintText[150];
char ganonText[250];
u8 seedIcons[5];
u16 randomizerInf[8];
u16 randomizerInf[9];
u8 temporaryWeapon;
u16 adultTradeItems;
u8 pendingIceTrapCount;

View File

@ -303,7 +303,11 @@ typedef union {
SCmdAltHeaders altHeaders;
} SceneCmd; // size = 0x8
typedef enum {
#ifdef __cplusplus
enum SceneID : int {
#else
enum SceneID {
#endif
/* 0x00 */ SCENE_YDAN,
/* 0x01 */ SCENE_DDAN,
/* 0x02 */ SCENE_BDAN,
@ -416,7 +420,7 @@ typedef enum {
/* 0x6C */ SCENE_SASATEST,
/* 0x6D */ SCENE_TESTROOM,
/* 0x6E */ SCENE_ID_MAX
} SceneID;
};
// Scene commands

View File

@ -363,7 +363,7 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_TRIALS_DONE_SPIRIT_TRIAL, "TRIALS_DONE_SPIRIT_TRIAL" },
{ RAND_INF_TRIALS_DONE_SHADOW_TRIAL, "TRIALS_DONE_SHADOW_TRIAL" },
{ RAND_INF_COWS_MILKED_LINKS_HOUSE_COW, "COWS_MILKED_LINKS_HOUSE_COW" },
{ RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW, "COWS_MILKED_KF_LINKS_HOUSE_COW" },
{ RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW, "COWS_MILKED_HF_COW_GROTTO_COW" },
{ RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW, "COWS_MILKED_LLR_STABLES_LEFT_COW" },
{ RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW, "COWS_MILKED_LLR_STABLES_RIGHT_COW" },
@ -373,7 +373,6 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW, "COWS_MILKED_DMT_COW_GROTTO_COW" },
{ RAND_INF_COWS_MILKED_GV_COW, "COWS_MILKED_GV_COW" },
{ RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW, "COWS_MILKED_JABU_JABUS_BELLY_MQ_COW" },
{ RAND_INF_COWS_MILKED_HF_COW_GROTTO_GOSSIP_STONE, "COWS_MILKED_HF_COW_GROTTO_GOSSIP_STONE" },
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, "SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT" },
{ RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, "SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS" },

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@
#include "../../../include/z64item.h"
#include <memory>
#include <soh/Enhancements/randomizer/randomizerTypes.h>
#include "soh/Enhancements/randomizer/randomizer_check_objects.h"
#include <soh/Enhancements/custom-message/CustomMessageManager.h>
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
@ -65,8 +66,10 @@ class Randomizer {
std::string GetAdultAltarText() const;
std::string GetGanonText() const;
std::string GetGanonHintText() const;
RandomizerCheckObject GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams);
ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
ShopItemIdentity IdentifyShopItem(s32 sceneNum, u8 slotIndex);
CowIdentity IdentifyCow(s32 sceneNum, s32 posX, s32 posZ);
GetItemEntry GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId, bool checkObtainability = true);
GetItemEntry GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId, bool checkObtainability = true);
GetItemID GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId);

View File

@ -1067,3 +1067,8 @@ typedef struct ShopItemIdentity {
int32_t enGirlAShopItem;
int32_t itemPrice;
} ShopItemIdentity;
typedef struct CowIdentity {
RandomizerInf randomizerInf;
RandomizerCheck randomizerCheck;
} CowIdentity;

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,12 @@
#pragma once
#include "randomizerTypes.h"
#include <string>
#include <vector>
#include <map>
// Forward Declarations to avoid duplicate definition issues
enum ActorID : int;
enum SceneID : int;
// Check types based on main settings
typedef enum {
RCTYPE_STANDARD, // Base set of rando checks
@ -64,11 +67,20 @@ typedef enum {
RCAREA_INVALID
} RandomizerCheckArea;
#define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b)
#define RC_OBJECT(rc, rc_v_or_mq, rc_type, rc_area, actor_id, scene_id, actor_params, og_item_id, rc_shortname, rc_spoilername) \
{ rc, {rc, rc_v_or_mq, rc_type, rc_area, actor_id, scene_id, actor_params, og_item_id, false, rc_shortname, rc_spoilername} }
typedef struct {
RandomizerCheck rc;
RandomizerCheckVanillaOrMQ vOrMQ;
RandomizerCheckType rcType;
RandomizerCheckArea rcArea;
ActorID actorId;
SceneID sceneId;
int32_t actorParams;
GetItemID ogItemId;
bool visibleInImgui;
std::string rcShortName;
std::string rcSpoilerName;
@ -78,6 +90,7 @@ namespace RandomizerCheckObjects {
bool AreaIsDungeon(RandomizerCheckArea area);
bool AreaIsOverworld(RandomizerCheckArea area);
std::string GetRCAreaName(RandomizerCheckArea area);
std::map<RandomizerCheckArea, std::vector<RandomizerCheckObject>> GetAllRCObjects();
std::map<RandomizerCheck, RandomizerCheckObject> GetAllRCObjects();
std::map<RandomizerCheckArea, std::map<RandomizerCheck, RandomizerCheckObject>> GetAllRCObjectsByArea();
void UpdateImGuiVisibility();
}

View File

@ -17,7 +17,7 @@ typedef enum {
RAND_INF_TRIALS_DONE_SPIRIT_TRIAL,
RAND_INF_TRIALS_DONE_SHADOW_TRIAL,
RAND_INF_COWS_MILKED_LINKS_HOUSE_COW,
RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW,
RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW,
RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW,
RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW,
@ -27,7 +27,6 @@ typedef enum {
RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW,
RAND_INF_COWS_MILKED_GV_COW,
RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW,
RAND_INF_COWS_MILKED_HF_COW_GROTTO_GOSSIP_STONE,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS,
@ -65,6 +64,16 @@ typedef enum {
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE,
RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB,
RAND_INF_SCRUBS_PURCHASED_DEKU_TREE_MQ_DEKU_SCRUB,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT,
RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1,
RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_2,

View File

@ -1816,6 +1816,10 @@ extern "C" ShopItemIdentity Randomizer_IdentifyShopItem(s32 sceneNum, u8 slotInd
return OTRGlobals::Instance->gRandomizer->IdentifyShopItem(sceneNum, slotIndex);
}
extern "C" CowIdentity Randomizer_IdentifyCow(s32 sceneNum, s32 posX, s32 posZ) {
return OTRGlobals::Instance->gRandomizer->IdentifyCow(sceneNum, posX, posZ);
}
extern "C" CustomMessageEntry Randomizer_GetNaviMessage() {
u16 naviTextId = rand() % NUM_NAVI_MESSAGES;
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId);

View File

@ -112,6 +112,7 @@ u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams);
ScrubIdentity Randomizer_IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
ShopItemIdentity Randomizer_IdentifyShopItem(s32 sceneNum, u8 slotIndex);
CowIdentity Randomizer_IdentifyCow(s32 sceneNum, s32 posX, s32 posZ);
void Randomizer_LoadHintLocations(const char* spoilerFileName);
void Randomizer_LoadMerchantMessages(const char* spoilerFileName);
void Randomizer_LoadRequiredTrials(const char* spoilerFileName);

View File

@ -462,7 +462,7 @@ s32 DoorWarp1_PlayerInRange(DoorWarp1* this, GlobalContext* globalCtx) {
}
void GivePlayerRandoReward(DoorWarp1* this, Player* player, GlobalContext* globalCtx, u8 ruto, u8 adult) {
GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->actor.params, GI_NONE);
GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, 0x00, GI_NONE);
if (this->actor.parent != NULL && this->actor.parent->id == GET_PLAYER(globalCtx)->actor.id &&
!Flags_GetTreasure(globalCtx, 0x1F)) {

View File

@ -18,7 +18,6 @@ void func_809E0070(Actor* thisx, GlobalContext* globalCtx);
void func_809DF494(EnCow* this, GlobalContext* globalCtx);
void func_809DF6BC(EnCow* this, GlobalContext* globalCtx);
CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx);
void EnCow_MoveForRandomizer(EnCow* this, GlobalContext* globalCtx);
void func_809DF778(EnCow* this, GlobalContext* globalCtx);
void func_809DF7D8(EnCow* this, GlobalContext* globalCtx);
@ -215,61 +214,6 @@ void func_809DF730(EnCow* this, GlobalContext* globalCtx) {
}
}
CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx) {
struct CowInfo cowInfo;
cowInfo.randomizerInf = -1;
cowInfo.randomizerCheck = RC_UNKNOWN_CHECK;
switch (globalCtx->sceneNum) {
case SCENE_SOUKO: // Lon Lon Tower
if (this->actor.world.pos.x == -229 && this->actor.world.pos.z == 157) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_TOWER_LEFT_COW;
cowInfo.randomizerCheck = RC_LLR_TOWER_LEFT_COW;
} else if (this->actor.world.pos.x == -142 && this->actor.world.pos.z == -140) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_TOWER_RIGHT_COW;
cowInfo.randomizerCheck = RC_LLR_TOWER_RIGHT_COW;
}
break;
case SCENE_MALON_STABLE:
if (this->actor.world.pos.x == 116 && this->actor.world.pos.z == -254) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW;
cowInfo.randomizerCheck = RC_LLR_STABLES_RIGHT_COW;
} else if (this->actor.world.pos.x == -122 && this->actor.world.pos.z == -254) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW;
cowInfo.randomizerCheck = RC_LLR_STABLES_LEFT_COW;
}
break;
case SCENE_KAKUSIANA: // Grotto
if (this->actor.world.pos.x == 2444 && this->actor.world.pos.z == -471) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW;
cowInfo.randomizerCheck = RC_DMT_COW_GROTTO_COW;
} else if (this->actor.world.pos.x == 3485 && this->actor.world.pos.z == -291) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW;
cowInfo.randomizerCheck = RC_HF_COW_GROTTO_COW;
}
break;
case SCENE_LINK_HOME:
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LINKS_HOUSE_COW;
cowInfo.randomizerCheck = RC_KF_LINKS_HOUSE_COW;
break;
case SCENE_LABO: // Impa's house
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_KAK_IMPAS_HOUSE_COW;
cowInfo.randomizerCheck = RC_KAK_IMPAS_HOUSE_COW;
break;
case SCENE_SPOT09: // Gerudo Valley
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_GV_COW;
cowInfo.randomizerCheck = RC_GV_COW;
break;
case SCENE_BDAN: // Jabu's Belly
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW;
cowInfo.randomizerCheck = RC_JABU_JABUS_BELLY_MQ_COW;
break;
}
return cowInfo;
}
void EnCow_MoveForRandomizer(EnCow* this, GlobalContext* globalCtx) {
// Only move the cow body (the tail will be moved with the body)
if (this->actor.params != 0) {
@ -288,9 +232,9 @@ void EnCow_MoveForRandomizer(EnCow* this, GlobalContext* globalCtx) {
}
void EnCow_SetCowMilked(EnCow* this, GlobalContext* globalCtx) {
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
CowIdentity cowIdentity = Randomizer_IdentifyCow(globalCtx->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z);
Player* player = GET_PLAYER(globalCtx);
player->pendingFlag.flagID = cowInfo.randomizerInf;
player->pendingFlag.flagID = cowIdentity.randomizerInf;
player->pendingFlag.flagType = FLAG_RANDOMIZER_INF;
}
@ -336,14 +280,14 @@ void func_809DF8FC(EnCow* this, GlobalContext* globalCtx) {
}
bool EnCow_HasBeenMilked(EnCow* this, GlobalContext* globalCtx) {
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
return Flags_GetRandomizerInf(cowInfo.randomizerInf);
CowIdentity cowIdentity = Randomizer_IdentifyCow(globalCtx->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z);
return Flags_GetRandomizerInf(cowIdentity.randomizerInf);
}
void EnCow_GivePlayerRandomizedItem(EnCow* this, GlobalContext* globalCtx) {
if (!EnCow_HasBeenMilked(this, globalCtx)) {
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(cowInfo.randomizerCheck, GI_MILK);
CowIdentity cowIdentity = Randomizer_IdentifyCow(globalCtx->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z);
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(cowIdentity.randomizerCheck, GI_MILK);
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 10000.0f, 100.0f);
} else {
// once we've gotten the rando reward from the cow,

View File

@ -21,9 +21,4 @@ typedef struct EnCow {
/* 0x027C */ EnCowActionFunc actionFunc;
} EnCow; // size = 0x0280
typedef struct CowInfo {
RandomizerInf randomizerInf;
RandomizerCheck randomizerCheck;
} CowInfo;
#endif