mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-12-18 14:22:17 -05:00
Potsanity proof of concept
This commit is contained in:
parent
dad4ae0095
commit
fe7476a377
@ -457,7 +457,7 @@ u32 Actor_HasParent(Actor* actor, PlayState* play);
|
||||
// TODO: Rename the follwing 3 functions using whatever scheme we use when we rename func_8002F434 and func_8002F554.
|
||||
s32 GiveItemEntryWithoutActor(PlayState* play, GetItemEntry getItemEntry);
|
||||
s32 GiveItemEntryFromActor(Actor* actor, PlayState* play, GetItemEntry getItemEntry, f32 xzRange, f32 yRange);
|
||||
void GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemEntry getItemEntry);
|
||||
s32 GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemEntry getItemEntry);
|
||||
s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange);
|
||||
void func_8002F554(Actor* actor, PlayState* play, s32 getItemId);
|
||||
void func_8002F580(Actor* actor, PlayState* play);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "z64collision_check.h"
|
||||
#include "z64bgcheck.h"
|
||||
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
|
||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||
#include "z64actor_enum.h"
|
||||
|
||||
#define ACTOR_NUMBER_MAX 2000
|
||||
@ -285,6 +286,8 @@ typedef struct EnItem00 {
|
||||
/* 0x160 */ ColliderCylinder collider;
|
||||
s16 ogParams;
|
||||
GetItemEntry randoGiEntry;
|
||||
RandomizerCheck randoCheck;
|
||||
RandomizerInf randoInf;
|
||||
} EnItem00; // size = 0x1AC
|
||||
|
||||
// Only A_OBJ_SIGNPOST_OBLONG and A_OBJ_SIGNPOST_ARROW are used in room files.
|
||||
|
@ -515,6 +515,8 @@ const std::vector<FlagTable> flagTables = {
|
||||
{ RAND_INF_BONGO_BONGO_SOUL, "RAND_INF_BONGO_BONGO_SOUL" },
|
||||
{ RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" },
|
||||
{ RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" },
|
||||
|
||||
{ RAND_INF_SHUFFLE_POTS_MARKET_GUARD_HOUSE_CHILD_1, "RAND_INF_SHUFFLE_POTS_MARKET_GUARD_HOUSE_CHILD_1" },
|
||||
} },
|
||||
};
|
||||
|
||||
|
@ -17,6 +17,7 @@ enum class Category {
|
||||
cVanillaMap,
|
||||
cVanillaCompass,
|
||||
cAdultTrade,
|
||||
cPot,
|
||||
};
|
||||
|
||||
enum class OptionCategory {
|
||||
|
@ -1356,4 +1356,9 @@ void HintTable_Init_Exclude_Overworld() {
|
||||
//obscure text
|
||||
Text{"a #cow in a luxurious hole# offers", /*french*/"la #vache dans une grotte luxueuse# donne", /*spanish*/"una #vaca de un lujoso hoyo# brinda"},
|
||||
});
|
||||
|
||||
hintTable[RHT_SHUFFLE_POTS_MARKET_GUARD_HOUSE_1] = HintText::Exclude({
|
||||
//obscure text
|
||||
Text{"a #pot in a room# holds", /*french*/"a #pot in a room# holds", /*spanish*/"a #pot in a room# holds"},
|
||||
});
|
||||
}
|
||||
|
@ -574,6 +574,11 @@ static void PlaceVanillaCowMilk() {
|
||||
}
|
||||
}
|
||||
|
||||
static void PlaceVanillaPotContents() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
ctx->PlaceItemInLocation(RC_MARKET_GUARD_HOUSE_CHILD_POT_1, RG_GREEN_RUPEE, false, true);
|
||||
}
|
||||
|
||||
static void SetScarceItemPool() {
|
||||
ReplaceMaxItem(RG_PROGRESSIVE_BOMBCHUS, 3);
|
||||
ReplaceMaxItem(RG_BOMBCHU_5, 1);
|
||||
@ -726,6 +731,12 @@ void GenerateItemPool() {
|
||||
PlaceVanillaCowMilk();
|
||||
}
|
||||
|
||||
if (ctx->GetOption(RSK_SHUFFLE_POTS)) {
|
||||
AddItemToMainPool(RG_GREEN_RUPEE);
|
||||
} else {
|
||||
PlaceVanillaPotContents();
|
||||
}
|
||||
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MAGIC_BEANS)) {
|
||||
AddItemToMainPool(RG_MAGIC_BEAN_PACK);
|
||||
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
|
||||
|
@ -168,8 +168,9 @@ void AreaTable_Init_CastleTown() {
|
||||
|
||||
areaTable[RR_MARKET_GUARD_HOUSE] = Area("Market Guard House", "Market Guard House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_MARKET_10_BIG_POES, {[]{return IsAdult && BigPoeKill;}}),
|
||||
LocationAccess(RC_MARKET_GS_GUARD_HOUSE, {[]{return IsChild;}}),
|
||||
LocationAccess(RC_MARKET_10_BIG_POES, {[]{return IsAdult && BigPoeKill;}}),
|
||||
LocationAccess(RC_MARKET_GS_GUARD_HOUSE, {[]{return IsChild;}}),
|
||||
LocationAccess(RC_MARKET_GUARD_HOUSE_CHILD_POT_1, {[]{return CanBreakPots();}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_MARKET_ENTRANCE, {[]{return true;}}),
|
||||
|
@ -503,6 +503,10 @@ namespace Logic {
|
||||
}
|
||||
}
|
||||
|
||||
bool CanBreakPots() {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t GetDifficultyValueFromString(Rando::Option& glitchOption) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -380,6 +380,7 @@ bool CanPlay(bool song);
|
||||
bool CanUse(RandomizerGet itemName);
|
||||
bool HasProjectile(HasProjectileAge age);
|
||||
bool HasBossSoul(RandomizerGet itemName);
|
||||
bool CanBreakPots();
|
||||
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount);
|
||||
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched);
|
||||
bool CanDoGlitch(GlitchType glitch);
|
||||
|
@ -118,6 +118,10 @@ void WriteIngameSpoilerLog() {
|
||||
if (!ctx->GetOption(RSK_SHUFFLE_COWS) && loc->IsCategory(Category::cCow)) {
|
||||
continue;
|
||||
}
|
||||
// Shuffle Pots
|
||||
else if (!ctx->GetOption(RSK_SHUFFLE_POTS) && loc->IsCategory(Category::cPot)) {
|
||||
continue;
|
||||
}
|
||||
// Merchants
|
||||
else if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_OFF) && loc->IsCategory(Category::cMerchant)) {
|
||||
continue;
|
||||
|
@ -28,6 +28,7 @@ typedef enum {
|
||||
SPOILER_CHK_MERCHANT,
|
||||
SPOILER_CHK_GRAVEDIGGER,
|
||||
SPOILER_CHK_RANDOMIZER_INF,
|
||||
SPOILER_CHK_POT,
|
||||
} SpoilerCollectionCheckType;
|
||||
|
||||
// GetLocation groups for checks, used to group the checks by logical location
|
||||
|
@ -94,6 +94,10 @@ class SpoilerCollectionCheck {
|
||||
static auto RandomizerInf(const int8_t scene, const uint8_t flag) {
|
||||
return SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, scene, flag);
|
||||
}
|
||||
|
||||
static auto Pot(const uint8_t scene, const uint8_t flag) {
|
||||
return SpoilerCollectionCheck(SPOILER_CHK_POT, scene, flag);
|
||||
}
|
||||
};
|
||||
|
||||
enum class LocationType {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "static_data.h"
|
||||
|
||||
#define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b)
|
||||
#define THREE_ACTOR_PARAMS(a, b, c) (abs(a) << 10) | (abs(a) << 20) | abs(c)
|
||||
|
||||
std::array<Rando::Location, RC_MAX> Rando::StaticData::locationTable;
|
||||
|
||||
@ -207,6 +208,7 @@ std::vector<RandomizerCheck> Rando::StaticData::overworldLocations = {
|
||||
RC_MARKET_TREASURE_CHEST_GAME_ITEM_3,
|
||||
RC_MARKET_TREASURE_CHEST_GAME_ITEM_4,
|
||||
RC_MARKET_TREASURE_CHEST_GAME_ITEM_5,
|
||||
RC_MARKET_GUARD_HOUSE_CHILD_POT_1,
|
||||
|
||||
// Market Shops
|
||||
RC_MARKET_BOMBCHU_SHOP_ITEM_1,
|
||||
@ -1291,6 +1293,9 @@ void Rando::StaticData::InitLocationTable() {
|
||||
locationTable[RC_GV_COW] = Location::Base(RC_GV_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_GERUDO_VALLEY, ACTOR_EN_COW, SCENE_GERUDO_VALLEY, 0x00, 0x15, "Cow", "GV Cow", RHT_GV_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x5A, 0x15), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
||||
locationTable[RC_JABU_JABUS_BELLY_MQ_COW] = Location::Base(RC_JABU_JABUS_BELLY_MQ_COW, RCQUEST_MQ, RCTYPE_COW, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_COW, SCENE_JABU_JABU, 0x00, 0x15, "MQ Cow", "Jabu Jabus Belly MQ Cow", RHT_JABU_JABUS_BELLY_MQ_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x02, 0x15), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY);
|
||||
|
||||
// Pots Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group
|
||||
locationTable[RC_MARKET_GUARD_HOUSE_CHILD_POT_1] = Location::Base(RC_MARKET_GUARD_HOUSE_CHILD_POT_1, RCQUEST_BOTH, RCTYPE_POT, RCAREA_MARKET, ACTOR_OBJ_TSUBO, SCENE_MARKET_GUARD_HOUSE, THREE_ACTOR_PARAMS(-80, 0, -7), 0x00, "Guard House Child Pot 1", "MK Guard House Child Pot 1", RHT_SHUFFLE_POTS_MARKET_GUARD_HOUSE_1, RG_GREEN_RUPEE, { Category::cPot }, SpoilerCollectionCheck::Pot(0x4D, 0x00), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
||||
|
||||
/*-------------------------------
|
||||
--- SHOPS ---
|
||||
8 6 2 4
|
||||
|
@ -414,7 +414,7 @@ bool OptionGroup::RenderImGui() const { // NOLINT(*-no-recursion)
|
||||
ImGui::Unindent();
|
||||
}
|
||||
if (option->HasFlag(IMFLAG_SEPARATOR_BOTTOM)) {
|
||||
UIWidgets::PaddedSeparator();
|
||||
UIWidgets::PaddedSeparator(false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -229,6 +229,8 @@ void Settings::CreateOptionDescriptions() {
|
||||
"\n"
|
||||
"The Gerudo Card is required to enter the Gerudo Training Grounds, opening "
|
||||
"the gate to Haunted Wasteland and the Horseback Archery minigame.";
|
||||
mOptionDescriptions[RSK_SHUFFLE_POTS] =
|
||||
"Freestanding pots will drop a randomized item the first time they're broken and collected. Pots will have a different appearance when they hold a randomized item.";
|
||||
mOptionDescriptions[RSK_SHOPSANITY] = "Off - All shop items will be the same as vanilla.\n"
|
||||
"\n"
|
||||
"0 Items - Vanilla shop items will be shuffled among different shops.\n"
|
||||
|
@ -1402,6 +1402,7 @@ std::map<RandomizerCheck, RandomizerInf> rcToRandomizerInf = {
|
||||
{ RC_LH_ADULT_FISHING, RAND_INF_ADULT_FISHING },
|
||||
{ RC_MARKET_10_BIG_POES, RAND_INF_10_BIG_POES },
|
||||
{ RC_KAK_100_GOLD_SKULLTULA_REWARD, RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD },
|
||||
{ RC_MARKET_GUARD_HOUSE_CHILD_POT_1, RAND_INF_SHUFFLE_POTS_MARKET_GUARD_HOUSE_CHILD_1 },
|
||||
};
|
||||
|
||||
Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams = 0x00) {
|
||||
@ -1609,6 +1610,24 @@ CowIdentity Randomizer::IdentifyCow(s32 sceneNum, s32 posX, s32 posZ) {
|
||||
return cowIdentity;
|
||||
}
|
||||
|
||||
PotIdentity Randomizer::IdentifyPot(s32 sceneNum, s32 posX, s32 posY, s32 posZ) {
|
||||
struct PotIdentity potIdentity;
|
||||
|
||||
potIdentity.randomizerInf = RAND_INF_MAX;
|
||||
potIdentity.randomizerCheck = RC_UNKNOWN_CHECK;
|
||||
|
||||
s32 actorParams = THREE_ACTOR_PARAMS(posX, posY, posZ);
|
||||
|
||||
Rando::Location* location = GetCheckObjectFromActor(ACTOR_OBJ_TSUBO, sceneNum, actorParams);
|
||||
|
||||
if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) {
|
||||
potIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()];
|
||||
potIdentity.randomizerCheck = location->GetRandomizerCheck();
|
||||
}
|
||||
|
||||
return potIdentity;
|
||||
}
|
||||
|
||||
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
|
||||
return Rando::Context::GetInstance()->GetOption(randoSettingKey).GetSelectedOptionIndex();
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ class Randomizer {
|
||||
ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
|
||||
ShopItemIdentity IdentifyShopItem(s32 sceneNum, u8 slotIndex);
|
||||
CowIdentity IdentifyCow(s32 sceneNum, s32 posX, s32 posZ);
|
||||
PotIdentity IdentifyPot(s32 sceneNum, s32 posX, s32 potY, 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);
|
||||
|
@ -101,10 +101,11 @@ typedef enum {
|
||||
RCTYPE_CHEST_GAME, // todo replace this once we implement it, just using it to exclude for now
|
||||
RCTYPE_LINKS_POCKET, // todo this feels hacky
|
||||
RCTYPE_GOSSIP_STONE,
|
||||
RCTYPE_SONG_LOCATION, // Song locations
|
||||
RCTYPE_SONG_LOCATION, // Song locations
|
||||
RCTYPE_BOSS_HEART_OR_OTHER_REWARD, // Boss heart container or lesser dungeon rewards (lens, ice arrow)
|
||||
RCTYPE_DUNGEON_REWARD, // Dungeon rewards (blue warps)
|
||||
RCTYPE_OCARINA, // Ocarina locations
|
||||
RCTYPE_DUNGEON_REWARD, // Dungeon rewards (blue warps)
|
||||
RCTYPE_OCARINA, // Ocarina locations
|
||||
RCTYPE_POT, // Shuffle Pots
|
||||
} RandomizerCheckType;
|
||||
|
||||
typedef enum { RCQUEST_VANILLA, RCQUEST_MQ, RCQUEST_BOTH } RandomizerCheckQuest;
|
||||
@ -746,6 +747,7 @@ typedef enum {
|
||||
RC_MARKET_BOMBCHU_SHOP_ITEM_6,
|
||||
RC_MARKET_BOMBCHU_SHOP_ITEM_7,
|
||||
RC_MARKET_BOMBCHU_SHOP_ITEM_8,
|
||||
RC_MARKET_GUARD_HOUSE_CHILD_POT_1,
|
||||
RC_TOT_LIGHT_ARROWS_CUTSCENE,
|
||||
RC_TOT_MASTER_SWORD,
|
||||
RC_HC_MALON_EGG,
|
||||
@ -3277,6 +3279,8 @@ typedef enum {
|
||||
RHT_CARPET_SALESMAN_DIALOG_THIRD,
|
||||
RHT_CARPET_SALESMAN_DIALOG_FOURTH,
|
||||
RHT_GRANNY_DIALOG,
|
||||
// Shuffle Pots
|
||||
RHT_SHUFFLE_POTS_MARKET_GUARD_HOUSE_1,
|
||||
RHT_MAX
|
||||
} RandomizerHintTextKey;
|
||||
|
||||
@ -3400,6 +3404,7 @@ typedef enum {
|
||||
RSK_SHUFFLE_COWS,
|
||||
RSK_SHUFFLE_WEIRD_EGG,
|
||||
RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD,
|
||||
RSK_SHUFFLE_POTS,
|
||||
RSK_SHUFFLE_FROG_SONG_RUPEES,
|
||||
RSK_ITEM_POOL,
|
||||
RSK_ICE_TRAPS,
|
||||
@ -3881,6 +3886,11 @@ typedef struct CowIdentity {
|
||||
RandomizerCheck randomizerCheck;
|
||||
} CowIdentity;
|
||||
|
||||
typedef struct PotIdentity {
|
||||
RandomizerInf randomizerInf;
|
||||
RandomizerCheck randomizerCheck;
|
||||
} PotIdentity;
|
||||
|
||||
typedef enum {
|
||||
TRACKER_WINDOW_FLOATING,
|
||||
TRACKER_WINDOW_WINDOW
|
||||
|
@ -153,6 +153,7 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() {
|
||||
((CVarGetInteger("gRandomizeShuffleTokens", RO_TOKENSANITY_OFF) == RO_TOKENSANITY_DUNGEONS) &&
|
||||
RandomizerCheckObjects::AreaIsDungeon(location.GetArea()))) &&
|
||||
(location.GetRCType() != RCTYPE_COW || CVarGetInteger("gRandomizeShuffleCows", RO_GENERIC_NO)) &&
|
||||
(location.GetRCType() != RCTYPE_POT || CVarGetInteger("gRandomizeShufflePotContents", RO_GENERIC_NO)) &&
|
||||
(location.GetRCType() != RCTYPE_ADULT_TRADE ||
|
||||
CVarGetInteger("gRandomizeShuffleAdultTrade", RO_GENERIC_NO)) &&
|
||||
(location.GetRandomizerCheck() != RC_KF_KOKIRI_SWORD_CHEST ||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <map>
|
||||
|
||||
#define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b)
|
||||
#define THREE_ACTOR_PARAMS(a, b, c) (abs(a) << 10) | (abs(a) << 20) | abs(c)
|
||||
|
||||
namespace RandomizerCheckObjects {
|
||||
bool AreaIsDungeon(RandomizerCheckArea area);
|
||||
|
@ -64,6 +64,7 @@ bool showKokiriSword;
|
||||
bool showMasterSword;
|
||||
bool showWeirdEgg;
|
||||
bool showGerudoCard;
|
||||
bool showPots;
|
||||
bool showFrogSongRupees;
|
||||
bool showStartingMapsCompasses;
|
||||
bool showKeysanity;
|
||||
@ -426,6 +427,7 @@ bool HasItemBeenCollected(RandomizerCheck rc) {
|
||||
case SpoilerCollectionCheckType::SPOILER_CHK_SCRUB:
|
||||
case SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF:
|
||||
case SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD:
|
||||
case SpoilerCollectionCheckType::SPOILER_CHK_POT:
|
||||
return Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc));
|
||||
case SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF:
|
||||
return gSaveContext.eventChkInf[flag / 16] & (0x01 << flag % 16);
|
||||
@ -1030,6 +1032,9 @@ void LoadSettings() {
|
||||
showGerudoCard = IS_RANDO ?
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD) == RO_GENERIC_YES
|
||||
: true;
|
||||
showPots = IS_RANDO ?
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_POTS) == RO_GENERIC_YES
|
||||
: true;
|
||||
showFrogSongRupees = IS_RANDO ?
|
||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_FROG_SONG_RUPEES) == RO_GENERIC_YES
|
||||
: false;
|
||||
@ -1132,6 +1137,7 @@ bool IsVisibleInCheckTracker(RandomizerCheck rc) {
|
||||
(showDungeonTokens && RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()))
|
||||
) &&
|
||||
(loc->GetRCType() != RCTYPE_COW || showCows) &&
|
||||
(loc->GetRCType() != RCTYPE_POT || showPots) &&
|
||||
(loc->GetRCType() != RCTYPE_ADULT_TRADE ||
|
||||
showAdultTrade ||
|
||||
rc == RC_KAK_ANJU_AS_ADULT || // adult trade checks that are always shuffled
|
||||
|
@ -170,6 +170,8 @@ typedef enum {
|
||||
RAND_INF_TWINROVA_SOUL,
|
||||
RAND_INF_GANON_SOUL,
|
||||
|
||||
RAND_INF_SHUFFLE_POTS_MARKET_GUARD_HOUSE_CHILD_1,
|
||||
|
||||
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
|
||||
|
||||
RAND_INF_MAX,
|
||||
|
@ -105,6 +105,7 @@ void Settings::CreateOptions() {
|
||||
mOptions[RSK_SHUFFLE_OCARINA] = Option::Bool("Shuffle Ocarinas", "gRandomizeShuffleOcarinas", mOptionDescriptions[RSK_SHUFFLE_OCARINA]);
|
||||
mOptions[RSK_SHUFFLE_WEIRD_EGG] = Option::Bool("Shuffle Weird Egg", "gRandomizeShuffleWeirdEgg", mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]);
|
||||
mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = Option::Bool("Shuffle Gerudo Membership Card", "gRandomizeShuffleGerudoToken", mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
|
||||
mOptions[RSK_SHUFFLE_POTS] = Option::Bool("Shuffle Pot Contents", "gRandomizeShufflePotContents", mOptionDescriptions[RSK_SHUFFLE_POTS]);
|
||||
mOptions[RSK_SHUFFLE_MAGIC_BEANS] = Option::Bool("Shuffle Magic Beans", "gRandomizeShuffleBeans", mOptionDescriptions[RSK_SHUFFLE_MAGIC_BEANS]);
|
||||
mOptions[RSK_SHUFFLE_MERCHANTS] = Option::U8("Shuffle Merchants", {"Off", "On (No Hints)", "On (With Hints)"}, OptionCategory::Setting, "gRandomizeShuffleMerchants", mOptionDescriptions[RSK_SHUFFLE_MERCHANTS], WidgetType::Combobox, RO_SHUFFLE_MERCHANTS_OFF);
|
||||
mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES] = Option::Bool("Shuffle Frog Song Rupees", "gRandomizeShuffleFrogSongRupees", mOptionDescriptions[RSK_SHUFFLE_FROG_SONG_RUPEES]);
|
||||
@ -614,7 +615,8 @@ void Settings::CreateOptions() {
|
||||
&mOptions[RSK_SHUFFLE_MASTER_SWORD],
|
||||
&mOptions[RSK_SHUFFLE_OCARINA],
|
||||
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
|
||||
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]
|
||||
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
|
||||
&mOptions[RSK_SHUFFLE_POTS]
|
||||
}, false, WidgetContainerType::COLUMN);
|
||||
mOptionGroups[RSG_SHUFFLE_NPCS_IMGUI] = OptionGroup::SubGroup("Shuffle NPCs & Merchants", {
|
||||
&mOptions[RSK_SHOPSANITY],
|
||||
@ -813,6 +815,7 @@ void Settings::CreateOptions() {
|
||||
&mOptions[RSK_SHUFFLE_OCARINA],
|
||||
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
|
||||
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
|
||||
&mOptions[RSK_SHUFFLE_POTS],
|
||||
&mOptions[RSK_SHUFFLE_MAGIC_BEANS],
|
||||
&mOptions[RSK_SHUFFLE_MERCHANTS],
|
||||
&mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES],
|
||||
@ -1009,6 +1012,7 @@ void Settings::CreateOptions() {
|
||||
{ "Shuffle Settings:Link's Pocket", RSK_LINKS_POCKET },
|
||||
{ "Shuffle Settings:Shuffle Songs", RSK_SHUFFLE_SONGS },
|
||||
{ "Shuffle Settings:Shuffle Gerudo Membership Card", RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD },
|
||||
{ "Shuffle Settings:Shuffle Pot Contents", RSK_SHUFFLE_POTS },
|
||||
{ "Shuffle Settings:Shopsanity", RSK_SHOPSANITY },
|
||||
{ "Shuffle Settings:Shopsanity Prices", RSK_SHOPSANITY_PRICES },
|
||||
{ "Shuffle Settings:Affordable Prices", RSK_SHOPSANITY_PRICES_AFFORDABLE },
|
||||
@ -2060,6 +2064,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) {
|
||||
}
|
||||
break;
|
||||
case RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD:
|
||||
case RSK_SHUFFLE_POTS:
|
||||
case RSK_SHUFFLE_COWS:
|
||||
case RSK_SHUFFLE_ADULT_TRADE:
|
||||
case RSK_SHUFFLE_MAGIC_BEANS:
|
||||
|
@ -1987,6 +1987,10 @@ extern "C" CowIdentity Randomizer_IdentifyCow(s32 sceneNum, s32 posX, s32 posZ)
|
||||
return OTRGlobals::Instance->gRandomizer->IdentifyCow(sceneNum, posX, posZ);
|
||||
}
|
||||
|
||||
extern "C" PotIdentity Randomizer_IdentifyPot(s32 sceneNum, s32 posX, s32 posY, s32 posZ) {
|
||||
return OTRGlobals::Instance->gRandomizer->IdentifyPot(sceneNum, posX, posY, posZ);
|
||||
}
|
||||
|
||||
extern "C" GetItemEntry ItemTable_Retrieve(int16_t getItemID) {
|
||||
GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, getItemID);
|
||||
return giEntry;
|
||||
|
@ -133,6 +133,7 @@ RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 sceneNum, s16 acto
|
||||
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);
|
||||
PotIdentity Randomizer_IdentifyPot(s32 sceneNum, s32 posX, s32 posY, s32 posZ);
|
||||
void Randomizer_ParseSpoiler(const char* fileLoc);
|
||||
void Randomizer_LoadHintMessages();
|
||||
void Randomizer_LoadMerchantMessages();
|
||||
|
@ -2055,8 +2055,8 @@ s32 GiveItemEntryFromActor(Actor* actor, PlayState* play, GetItemEntry getItemEn
|
||||
* \param play the Global Context
|
||||
* \param getItemEntry the GetItemEntry for the item you want the player to receive.
|
||||
*/
|
||||
void GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemEntry getItemEntry) {
|
||||
GiveItemEntryFromActor(actor, play, getItemEntry, 50.0f, 10.0f);
|
||||
s32 GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemEntry getItemEntry) {
|
||||
return GiveItemEntryFromActor(actor, play, getItemEntry, 50.0f, 10.0f);
|
||||
}
|
||||
|
||||
// TODO: Rename to GiveItemIdFromActor or similar
|
||||
|
@ -348,6 +348,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
|
||||
f32 shadowScale = 6.0f;
|
||||
s32 getItemId = GI_NONE;
|
||||
this->randoGiEntry = (GetItemEntry)GET_ITEM_NONE;
|
||||
this->randoCheck = (RandomizerCheck)RC_UNKNOWN_CHECK;
|
||||
s16 spawnParam8000 = this->actor.params & 0x8000;
|
||||
s32 pad1;
|
||||
|
||||
@ -485,12 +486,11 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
|
||||
this->actor.shape.shadowAlpha = 180;
|
||||
this->actor.focus.pos = this->actor.world.pos;
|
||||
this->getItemId = GI_NONE;
|
||||
RandomizerCheck randoCheck =
|
||||
Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams);
|
||||
this->randoCheck = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams);
|
||||
this->randoInf = RAND_INF_MAX;
|
||||
|
||||
if (IS_RANDO && randoCheck != RC_UNKNOWN_CHECK) {
|
||||
this->randoGiEntry =
|
||||
Randomizer_GetItemFromKnownCheck(randoCheck, getItemId);
|
||||
if (IS_RANDO && this->randoCheck != RC_UNKNOWN_CHECK) {
|
||||
this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, getItemId);
|
||||
this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING;
|
||||
}
|
||||
|
||||
@ -581,7 +581,10 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
|
||||
if (!IS_RANDO || this->randoGiEntry.getItemId == GI_NONE) {
|
||||
func_8002F554(&this->actor, play, getItemId);
|
||||
} else {
|
||||
GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry);
|
||||
if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) &&
|
||||
this->randoInf != RAND_INF_MAX) {
|
||||
Flags_SetRandomizerInf(this->randoInf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -734,7 +737,10 @@ void func_8001E5C8(EnItem00* this, PlayState* play) {
|
||||
if (!IS_RANDO) {
|
||||
func_8002F434(&this->actor, play, this->getItemId, 50.0f, 80.0f);
|
||||
} else {
|
||||
GiveItemEntryFromActor(&this->actor, play, this->randoGiEntry, 50.0f, 80.0f);
|
||||
if (GiveItemEntryFromActor(&this->actor, play, this->randoGiEntry, 50.0f, 80.0f) &&
|
||||
this->randoInf != RAND_INF_MAX) {
|
||||
Flags_SetRandomizerInf(this->randoInf);
|
||||
}
|
||||
}
|
||||
this->unk_15A++;
|
||||
} else {
|
||||
@ -955,7 +961,10 @@ void EnItem00_Update(Actor* thisx, PlayState* play) {
|
||||
func_8002F554(&this->actor, play, getItemId);
|
||||
} else {
|
||||
getItemId = this->randoGiEntry.getItemId;
|
||||
GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry);
|
||||
if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) &&
|
||||
this->randoInf != RAND_INF_MAX) {
|
||||
Flags_SetRandomizerInf(this->randoInf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1363,12 +1372,8 @@ static const Vtx customDropVtx[] = {
|
||||
*/
|
||||
void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) {
|
||||
if (IS_RANDO && (this->getItemId != GI_NONE || this->actor.params == ITEM00_SMALL_KEY)) {
|
||||
RandomizerCheck randoCheck =
|
||||
Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams);
|
||||
|
||||
if (randoCheck != RC_UNKNOWN_CHECK) {
|
||||
this->randoGiEntry =
|
||||
Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE);
|
||||
if (this->randoCheck != RC_UNKNOWN_CHECK) {
|
||||
this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, GI_NONE);
|
||||
this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING;
|
||||
}
|
||||
|
||||
@ -1457,12 +1462,8 @@ void EnItem00_DrawHeartContainer(EnItem00* this, PlayState* play) {
|
||||
*/
|
||||
void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) {
|
||||
if (IS_RANDO) {
|
||||
RandomizerCheck randoCheck =
|
||||
Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams);
|
||||
|
||||
if (randoCheck != RC_UNKNOWN_CHECK) {
|
||||
this->randoGiEntry =
|
||||
Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE);
|
||||
if (this->randoCheck != RC_UNKNOWN_CHECK) {
|
||||
this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, GI_NONE);
|
||||
this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,29 @@ static InitChainEntry sInitChain[] = {
|
||||
ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 800, ICHAIN_STOP),
|
||||
};
|
||||
|
||||
s8 ObjTsubo_HoldsRandomizedItem(ObjTsubo* this, PlayState* play) {
|
||||
return Randomizer_GetSettingValue(RSK_SHUFFLE_POTS) &&
|
||||
!Flags_GetRandomizerInf(this->potIdentity.randomizerInf) &&
|
||||
this->potIdentity.randomizerCheck != RC_UNKNOWN_CHECK;
|
||||
}
|
||||
|
||||
void ObjTsubo_SpawnCollectible(ObjTsubo* this, PlayState* play) {
|
||||
|
||||
if (IS_RANDO && ObjTsubo_HoldsRandomizedItem(this, play)) {
|
||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(this->potIdentity.randomizerCheck, GI_NONE);
|
||||
|
||||
EnItem00* actor = (EnItem00*)Item_DropCollectible2(play, &this->actor.world.pos, ITEM00_SMALL_KEY);
|
||||
actor->randoCheck = this->potIdentity.randomizerCheck;
|
||||
actor->randoGiEntry = getItemEntry;
|
||||
actor->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING;
|
||||
actor->randoInf = this->potIdentity.randomizerInf;
|
||||
actor->actor.velocity.y = 8.0f;
|
||||
actor->actor.speedXZ = 2.0f;
|
||||
actor->actor.gravity = -0.9f;
|
||||
actor->actor.world.rot.y = Rand_CenteredFloat(65536.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
s16 dropParams = this->actor.params & 0x1F;
|
||||
|
||||
if ((dropParams >= ITEM00_RUPEE_GREEN) && (dropParams <= ITEM00_BOMBS_SPECIAL)) {
|
||||
@ -145,6 +167,16 @@ void ObjTsubo_Init(Actor* thisx, PlayState* play) {
|
||||
ObjTsubo_SetupWaitForObject(this);
|
||||
osSyncPrintf("(dungeon keep 壷)(arg_data 0x%04x)\n", this->actor.params);
|
||||
}
|
||||
if (IS_RANDO) {
|
||||
this->potIdentity = Randomizer_IdentifyPot(play->sceneNum, (s16)this->actor.world.pos.x,
|
||||
(s16)this->actor.world.pos.y, (s16)this->actor.world.pos.z);
|
||||
|
||||
if (ObjTsubo_HoldsRandomizedItem(this, play)) {
|
||||
this->actor.scale.x = 0.1f;
|
||||
this->actor.scale.y = 0.1f;
|
||||
this->actor.scale.z = 0.1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjTsubo_Destroy(Actor* thisx, PlayState* play2) {
|
||||
|
@ -13,6 +13,7 @@ typedef struct ObjTsubo {
|
||||
/* 0x014C */ ObjTsuboActionFunc actionFunc;
|
||||
/* 0x0150 */ ColliderCylinder collider;
|
||||
/* 0x019C */ s8 objTsuboBankIndex;
|
||||
/* */ PotIdentity potIdentity;
|
||||
} ObjTsubo; // size = 0x01A0
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user