mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-04-28 13:17:58 +03:00
Merge 007228485e
into fbbfc07ff1
This commit is contained in:
commit
18ec39cb34
19 changed files with 97 additions and 90 deletions
|
@ -316,7 +316,7 @@ const std::vector<PresetEntry> randomizerBeginnerPresetEntries = {
|
||||||
|
|
||||||
// Gamplay tab
|
// Gamplay tab
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
||||||
|
@ -387,7 +387,7 @@ const std::vector<PresetEntry> randomizerStandardPresetEntries = {
|
||||||
|
|
||||||
// Gamplay tab
|
// Gamplay tab
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
||||||
|
@ -469,7 +469,7 @@ const std::vector<PresetEntry> randomizerAdvancedPresetEntries = {
|
||||||
|
|
||||||
// Gamplay tab
|
// Gamplay tab
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
|
||||||
|
@ -568,7 +568,7 @@ const std::vector<PresetEntry> hellModePresetEntries = {
|
||||||
|
|
||||||
// Gamplay tab
|
// Gamplay tab
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),
|
||||||
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1),
|
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1),
|
||||||
|
|
|
@ -162,6 +162,7 @@ typedef enum {
|
||||||
TEXT_ANJU_THANKS_FOR_FINDING_MY_CUCCOS = 0x503B,
|
TEXT_ANJU_THANKS_FOR_FINDING_MY_CUCCOS = 0x503B,
|
||||||
TEXT_ANJU_ROUND_THEM_UP_OR_YOULL_PAY = 0x503C,
|
TEXT_ANJU_ROUND_THEM_UP_OR_YOULL_PAY = 0x503C,
|
||||||
TEXT_ANJU_DONT_TEASE_MY_CUCCOS = 0x503D,
|
TEXT_ANJU_DONT_TEASE_MY_CUCCOS = 0x503D,
|
||||||
|
TEXT_BIG_POE_COLLECTED_RANDO = 0x5090,
|
||||||
TEXT_HBA_NOT_ON_HORSE = 0x603F,
|
TEXT_HBA_NOT_ON_HORSE = 0x603F,
|
||||||
TEXT_HBA_INITIAL_EXPLAINATION = 0x6040,
|
TEXT_HBA_INITIAL_EXPLAINATION = 0x6040,
|
||||||
TEXT_HBA_WANT_TO_TRY_AGAIN_YES_NO = 0x6041,
|
TEXT_HBA_WANT_TO_TRY_AGAIN_YES_NO = 0x6041,
|
||||||
|
|
|
@ -228,6 +228,14 @@ typedef enum {
|
||||||
// - `*Actor` (interactRangeActor)
|
// - `*Actor` (interactRangeActor)
|
||||||
VB_BOTTLE_ACTOR,
|
VB_BOTTLE_ACTOR,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*EnPoField`
|
||||||
|
VB_BOTTLE_BIG_POE,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// ((this->actor.params == DNS_TYPE_HEART_PIECE) && (Flags_GetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE))) ||
|
// ((this->actor.params == DNS_TYPE_HEART_PIECE) && (Flags_GetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE))) ||
|
||||||
|
@ -1663,6 +1671,14 @@ typedef enum {
|
||||||
// - `*EnRu1`
|
// - `*EnRu1`
|
||||||
VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE,
|
VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE,
|
||||||
|
|
||||||
|
// #### `result`
|
||||||
|
// ```c
|
||||||
|
// true
|
||||||
|
// ```
|
||||||
|
// #### `args`
|
||||||
|
// - `*EnGb`
|
||||||
|
VB_SELL_POES_TO_POE_COLLECTOR,
|
||||||
|
|
||||||
// #### `result`
|
// #### `result`
|
||||||
// ```c
|
// ```c
|
||||||
// true
|
// true
|
||||||
|
|
|
@ -159,11 +159,6 @@ static void ValidateOtherEntrance(GetAccessibleLocationsStruct& gals) {
|
||||||
ApplyStartingInventory(); // RANDOTODO when proper ammo logic is done, this could be moved to the start
|
ApplyStartingInventory(); // RANDOTODO when proper ammo logic is done, this could be moved to the start
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we are not shuffling the guard house, add the key so we can properly check for poe merchant access
|
|
||||||
if (gals.validatedStartingRegion && gals.foundTempleOfTime &&
|
|
||||||
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF)) {
|
|
||||||
Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply all items that are necessary for checking all location access
|
// Apply all items that are necessary for checking all location access
|
||||||
|
@ -180,10 +175,7 @@ static void ApplyAllAdvancmentItems() {
|
||||||
static void ValidateSphereZero(GetAccessibleLocationsStruct& gals) {
|
static void ValidateSphereZero(GetAccessibleLocationsStruct& gals) {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
// Condition for verifying everything required for sphere 0, expanding search to all locations
|
// Condition for verifying everything required for sphere 0, expanding search to all locations
|
||||||
if ((!logic->AreCheckingBigPoes || logic->CanEmptyBigPoes) && gals.validatedStartingRegion &&
|
if (gals.validatedStartingRegion && gals.foundTempleOfTime && gals.haveTimeAccess) {
|
||||||
gals.foundTempleOfTime && gals.haveTimeAccess) {
|
|
||||||
// stop checking for big poes
|
|
||||||
logic->AreCheckingBigPoes = false;
|
|
||||||
// Apply all items that are necessary for checking all location access
|
// Apply all items that are necessary for checking all location access
|
||||||
ApplyAllAdvancmentItems();
|
ApplyAllAdvancmentItems();
|
||||||
// Reset access as the non-starting age
|
// Reset access as the non-starting age
|
||||||
|
@ -213,7 +205,7 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer
|
||||||
// Update Time of Day Access for the exit
|
// Update Time of Day Access for the exit
|
||||||
if (UpdateToDAccess(&exit, exitRegion)) {
|
if (UpdateToDAccess(&exit, exitRegion)) {
|
||||||
gals.logicUpdated = true;
|
gals.logicUpdated = true;
|
||||||
if (!gals.sphereZeroComplete || logic->AreCheckingBigPoes) {
|
if (!gals.sphereZeroComplete) {
|
||||||
if (!gals.foundTempleOfTime || !gals.validatedStartingRegion) {
|
if (!gals.foundTempleOfTime || !gals.validatedStartingRegion) {
|
||||||
ValidateOtherEntrance(gals);
|
ValidateOtherEntrance(gals);
|
||||||
}
|
}
|
||||||
|
@ -596,15 +588,12 @@ bool CheckBeatable(RandomizerGet ignore /* = RG_NONE*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the currently randomised set of entrances is a valid game map.
|
// Check if the currently randomised set of entrances is a valid game map.
|
||||||
void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAccess) {
|
void ValidateEntrances(bool checkOtherEntranceAccess) {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
GetAccessibleLocationsStruct gals(0);
|
GetAccessibleLocationsStruct gals(0);
|
||||||
ResetLogic(ctx, gals, !checkOtherEntranceAccess);
|
ResetLogic(ctx, gals, !checkOtherEntranceAccess);
|
||||||
|
|
||||||
ctx->allLocationsReachable = false;
|
ctx->allLocationsReachable = false;
|
||||||
if (checkPoeCollectorAccess) {
|
|
||||||
logic->AreCheckingBigPoes = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checkOtherEntranceAccess) {
|
if (checkOtherEntranceAccess) {
|
||||||
gals.foundTempleOfTime = false;
|
gals.foundTempleOfTime = false;
|
||||||
|
@ -620,11 +609,6 @@ void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAcce
|
||||||
RegionTable(RR_ROOT)->adultNight = true;
|
RegionTable(RR_ROOT)->adultNight = true;
|
||||||
RegionTable(RR_ROOT)->childDay = true;
|
RegionTable(RR_ROOT)->childDay = true;
|
||||||
RegionTable(RR_ROOT)->adultDay = true;
|
RegionTable(RR_ROOT)->adultDay = true;
|
||||||
} else if (checkPoeCollectorAccess) {
|
|
||||||
// If we are not shuffling the guard house, add the key so we can properly check for poe merchant access
|
|
||||||
if (ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF)) {
|
|
||||||
Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ApplyAllAdvancmentItems();
|
ApplyAllAdvancmentItems();
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,4 +72,4 @@ void GeneratePlaythrough();
|
||||||
|
|
||||||
bool CheckBeatable(RandomizerGet ignore = RG_NONE);
|
bool CheckBeatable(RandomizerGet ignore = RG_NONE);
|
||||||
|
|
||||||
void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAccess);
|
void ValidateEntrances(bool checkOtherEntranceAccess);
|
|
@ -273,8 +273,8 @@ std::vector<std::pair<RandomizerCheck, std::function<bool()>>> conditionalAlways
|
||||||
std::make_pair(RC_MARKET_10_BIG_POES,
|
std::make_pair(RC_MARKET_10_BIG_POES,
|
||||||
[]() {
|
[]() {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
return ctx->GetOption(RSK_BIG_POE_COUNT).Get() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
|
return ctx->GetOption(RSK_BIG_POE_COUNT).Get() > 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
|
||||||
}), // Remember, the option's value being 3 means 4 are required
|
}),
|
||||||
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH,
|
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH,
|
||||||
[]() {
|
[]() {
|
||||||
auto ctx = Rando::Context::GetInstance();
|
auto ctx = Rando::Context::GetInstance();
|
||||||
|
|
|
@ -441,12 +441,6 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||||
type = entrancePlaced->GetType();
|
type = entrancePlaced->GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkPoeCollectorAccess =
|
|
||||||
(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) ||
|
|
||||||
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL)) &&
|
|
||||||
(entrancePlaced == nullptr || ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS) || type == EntranceType::Interior ||
|
|
||||||
type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn ||
|
|
||||||
type == EntranceType::WarpSong || type == EntranceType::OwlDrop);
|
|
||||||
bool checkOtherEntranceAccess =
|
bool checkOtherEntranceAccess =
|
||||||
(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) ||
|
(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) ||
|
||||||
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL) ||
|
ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL) ||
|
||||||
|
@ -459,7 +453,7 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||||
// Conditions will be checked during the search and any that fail will be figured out
|
// Conditions will be checked during the search and any that fail will be figured out
|
||||||
// afterwards
|
// afterwards
|
||||||
ctx->GetLogic()->Reset();
|
ctx->GetLogic()->Reset();
|
||||||
ValidateEntrances(checkPoeCollectorAccess, checkOtherEntranceAccess);
|
ValidateEntrances(checkOtherEntranceAccess);
|
||||||
|
|
||||||
if (!ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
if (!ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||||
// Unless entrances are decoupled, we don't want the player to end up through certain entrances as the wrong age
|
// Unless entrances are decoupled, we don't want the player to end up through certain entrances as the wrong age
|
||||||
|
@ -544,15 +538,6 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Big Poe shop should always be accessible as adult without the need to use any bottles
|
|
||||||
// This is important to ensure that players can never lock their only bottles by filling them with Big Poes they
|
|
||||||
// can't sell
|
|
||||||
if (checkPoeCollectorAccess) {
|
|
||||||
if (!RegionTable(RR_MARKET_GUARD_HOUSE)->Adult()) {
|
|
||||||
SPDLOG_DEBUG("Big Poe Shop access is not guarenteed as adult\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SPDLOG_DEBUG("All Locations NOT REACHABLE\n");
|
SPDLOG_DEBUG("All Locations NOT REACHABLE\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ extern "C" {
|
||||||
#include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h"
|
#include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h"
|
||||||
#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h"
|
#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h"
|
||||||
#include "src/overlays/actors/ovl_En_Gb/z_en_gb.h"
|
#include "src/overlays/actors/ovl_En_Gb/z_en_gb.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Po_Field/z_en_po_field.h"
|
||||||
#include "src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h"
|
#include "src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h"
|
||||||
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
|
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
|
||||||
#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h"
|
#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h"
|
||||||
|
@ -1080,12 +1081,35 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
|
||||||
*should = false;
|
*should = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VB_BOTTLE_BIG_POE: {
|
||||||
|
EnPoField* enPoe = va_arg(args, EnPoField*);
|
||||||
|
enPoe->actor.textId = 0x5090;
|
||||||
|
Flags_SetSwitch(gPlayState, enPoe->actor.params & 0xFF);
|
||||||
|
HIGH_SCORE(HS_POE_POINTS) += 100;
|
||||||
|
if (HIGH_SCORE(HS_POE_POINTS) > 1100) {
|
||||||
|
HIGH_SCORE(HS_POE_POINTS) = 1100;
|
||||||
|
}
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VB_SELL_POES_TO_POE_COLLECTOR: {
|
||||||
|
if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES) && HIGH_SCORE(HS_POE_POINTS) >= 1000) {
|
||||||
|
EnGb* enGb = va_arg(args, EnGb*);
|
||||||
|
enGb->textId = 0x70F8;
|
||||||
|
Message_ContinueTextbox(gPlayState, enGb->textId);
|
||||||
|
enGb->actionFunc = func_80A2FB40;
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case VB_GIVE_ITEM_FROM_POE_COLLECTOR: {
|
case VB_GIVE_ITEM_FROM_POE_COLLECTOR: {
|
||||||
EnGb* enGb = va_arg(args, EnGb*);
|
EnGb* enGb = va_arg(args, EnGb*);
|
||||||
if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES)) {
|
if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES)) {
|
||||||
|
Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET);
|
||||||
Flags_SetRandomizerInf(RAND_INF_10_BIG_POES);
|
Flags_SetRandomizerInf(RAND_INF_10_BIG_POES);
|
||||||
|
enGb->textId = 0x70F5;
|
||||||
enGb->dyna.actor.parent = NULL;
|
enGb->dyna.actor.parent = NULL;
|
||||||
enGb->actionFunc = func_80A2FC0C;
|
enGb->actionFunc = func_80A2F83C;
|
||||||
*should = false;
|
*should = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -324,9 +324,6 @@ void RegionTable_Init() {
|
||||||
areaTable[RR_ROOT] = Region("Root", "", {RA_LINKS_POCKET}, NO_DAY_NIGHT_CYCLE, {
|
areaTable[RR_ROOT] = Region("Root", "", {RA_LINKS_POCKET}, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&logic->KakarikoVillageGateOpen, []{return ctx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN);}),
|
EventAccess(&logic->KakarikoVillageGateOpen, []{return ctx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN);}),
|
||||||
//The big poes bottle softlock safety check does not account for the guard house lock if the guard house is not shuffled, so the key is needed before we can safely allow bottle use in logic
|
|
||||||
//RANDOTODO a setting that lets you drink/dump big poes so we don't need this logic
|
|
||||||
EventAccess(&logic->CouldEmptyBigPoes, []{return !ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) || logic->CanOpenOverworldDoor(RG_GUARD_HOUSE_KEY);}),
|
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_LINKS_POCKET, true),
|
LOCATION(RC_LINKS_POCKET, true),
|
||||||
|
|
|
@ -54,7 +54,7 @@ void RegionTable_Init_Market() {
|
||||||
EventAccess(&logic->CanEmptyBigPoes, []{return logic->IsAdult;}),
|
EventAccess(&logic->CanEmptyBigPoes, []{return logic->IsAdult;}),
|
||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->BigPoeKill || logic->BigPoes > ctx->GetOption(RSK_BIG_POE_COUNT).Get())),
|
LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->BigPoeKill || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())),
|
||||||
LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild),
|
LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild),
|
||||||
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_1, logic->IsChild && logic->CanBreakPots()),
|
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_1, logic->IsChild && logic->CanBreakPots()),
|
||||||
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_2, logic->IsChild && logic->CanBreakPots()),
|
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_2, logic->IsChild && logic->CanBreakPots()),
|
||||||
|
|
|
@ -1013,26 +1013,24 @@ Logic::Logic() {
|
||||||
|
|
||||||
uint8_t Logic::BottleCount() {
|
uint8_t Logic::BottleCount() {
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
if (CouldEmptyBigPoes && !AreCheckingBigPoes) {
|
for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_4; i++) {
|
||||||
for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_4; i++) {
|
uint8_t item = GetSaveContext()->inventory.items[i];
|
||||||
uint8_t item = GetSaveContext()->inventory.items[i];
|
switch (item) {
|
||||||
switch (item) {
|
case ITEM_LETTER_RUTO:
|
||||||
case ITEM_LETTER_RUTO:
|
if (DeliverLetter) {
|
||||||
if (DeliverLetter) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ITEM_BIG_POE:
|
|
||||||
if (CanEmptyBigPoes) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ITEM_NONE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
count++;
|
count++;
|
||||||
break;
|
}
|
||||||
}
|
break;
|
||||||
|
case ITEM_BIG_POE:
|
||||||
|
if (CanEmptyBigPoes) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ITEM_NONE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
count++;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
@ -2408,7 +2406,6 @@ void Logic::Reset() {
|
||||||
Bottles = 0;
|
Bottles = 0;
|
||||||
NumBottles = 0;
|
NumBottles = 0;
|
||||||
CanEmptyBigPoes = false;
|
CanEmptyBigPoes = false;
|
||||||
CouldEmptyBigPoes = false;
|
|
||||||
|
|
||||||
// Drops and Bottle Contents Access
|
// Drops and Bottle Contents Access
|
||||||
NutPot = false;
|
NutPot = false;
|
||||||
|
|
|
@ -66,12 +66,6 @@ class Logic {
|
||||||
uint8_t NumBottles = 0;
|
uint8_t NumBottles = 0;
|
||||||
// this event covers if the player can currently empty big poes in logic
|
// this event covers if the player can currently empty big poes in logic
|
||||||
bool CanEmptyBigPoes = false;
|
bool CanEmptyBigPoes = false;
|
||||||
// this event covers if the player could, if they filled their bottle with big poes in field, empty them at the poe
|
|
||||||
// merchant. Works in tandem with the big poes safety check during entrance validation
|
|
||||||
bool CouldEmptyBigPoes = false;
|
|
||||||
// this check is used to tell logic that we are checking big poes accessibility in logic, to ensure it's not
|
|
||||||
// bottle-locked.
|
|
||||||
bool AreCheckingBigPoes = false;
|
|
||||||
|
|
||||||
// Drops and Bottle Contents Access
|
// Drops and Bottle Contents Access
|
||||||
bool NutPot = false;
|
bool NutPot = false;
|
||||||
|
|
|
@ -334,7 +334,7 @@ extern "C" void Randomizer_InitSaveFile() {
|
||||||
Flags_SetRandomizerInf(RAND_INF_TOT_MASTER_SWORD);
|
Flags_SetRandomizerInf(RAND_INF_TOT_MASTER_SWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * (Randomizer_GetSettingValue(RSK_BIG_POE_COUNT) + 1));
|
HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT));
|
||||||
|
|
||||||
if (Randomizer_GetSettingValue(RSK_SKIP_EPONA_RACE)) {
|
if (Randomizer_GetSettingValue(RSK_SKIP_EPONA_RACE)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_EPONA_OBTAINED);
|
Flags_SetEventChkInf(EVENTCHKINF_EPONA_OBTAINED);
|
||||||
|
|
|
@ -268,7 +268,7 @@ void Settings::CreateOptions() {
|
||||||
OPT_BOOL(RSK_SKIP_CHILD_ZELDA, "Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
|
OPT_BOOL(RSK_SKIP_CHILD_ZELDA, "Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
|
||||||
OPT_BOOL(RSK_SKIP_EPONA_RACE, "Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
|
OPT_BOOL(RSK_SKIP_EPONA_RACE, "Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
|
||||||
OPT_BOOL(RSK_SKIP_SCARECROWS_SONG, "Skip Scarecrow's Song", CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]);
|
OPT_BOOL(RSK_SKIP_SCARECROWS_SONG, "Skip Scarecrow's Song", CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]);
|
||||||
OPT_U8(RSK_BIG_POE_COUNT, "Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9);
|
OPT_U8(RSK_BIG_POE_COUNT, "Big Poe Target Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 10);
|
||||||
OPT_U8(RSK_CUCCO_COUNT, "Cuccos to return", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("CuccosToReturn"), mOptionDescriptions[RSK_CUCCO_COUNT], WidgetType::Slider, 7);
|
OPT_U8(RSK_CUCCO_COUNT, "Cuccos to return", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("CuccosToReturn"), mOptionDescriptions[RSK_CUCCO_COUNT], WidgetType::Slider, 7);
|
||||||
OPT_BOOL(RSK_COMPLETE_MASK_QUEST, "Complete Mask Quest", CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_COMPLETE_MASK_QUEST]);
|
OPT_BOOL(RSK_COMPLETE_MASK_QUEST, "Complete Mask Quest", CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_COMPLETE_MASK_QUEST]);
|
||||||
OPT_U8(RSK_GOSSIP_STONE_HINTS, "Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GossipStoneHints"), mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WidgetType::Combobox, RO_GOSSIP_STONES_NEED_NOTHING, false, IMFLAG_NONE);
|
OPT_U8(RSK_GOSSIP_STONE_HINTS, "Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GossipStoneHints"), mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WidgetType::Combobox, RO_GOSSIP_STONES_NEED_NOTHING, false, IMFLAG_NONE);
|
||||||
|
|
|
@ -2426,6 +2426,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
||||||
CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT);
|
CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT);
|
||||||
} else if (textId == TEXT_MASK_SHOP_SIGN && ctx->GetOption(RSK_MASK_SHOP_HINT)) {
|
} else if (textId == TEXT_MASK_SHOP_SIGN && ctx->GetOption(RSK_MASK_SHOP_HINT)) {
|
||||||
messageEntry = ctx->GetHint(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT);
|
messageEntry = ctx->GetHint(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT);
|
||||||
|
} else if (textId == TEXT_BIG_POE_COLLECTED_RANDO) {
|
||||||
|
messageEntry =
|
||||||
|
CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
|
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
|
||||||
|
|
|
@ -172,4 +172,7 @@ extern "C" void OTRMessage_Init() {
|
||||||
CustomMessage("I'm sorry I can't sell you these fine specimens, they need an #experienced owner#.^"
|
CustomMessage("I'm sorry I can't sell you these fine specimens, they need an #experienced owner#.^"
|
||||||
"Come back when you have had #Bombchus# of your own.",
|
"Come back when you have had #Bombchus# of your own.",
|
||||||
{ QM_RED, QM_GREEN }));
|
{ QM_RED, QM_GREEN }));
|
||||||
|
CustomMessageManager::Instance->CreateMessage(
|
||||||
|
customMessageTableID, TEXT_BIG_POE_COLLECTED_RANDO,
|
||||||
|
CustomMessage("You have #" + CustomMessage::POINTS("\x01") + "# points.", { QM_RED }));
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,19 +288,21 @@ void func_80A2F83C(EnGb* this, PlayState* play) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Actor_ProcessTalkRequest(&this->dyna.actor, play)) {
|
if (Actor_ProcessTalkRequest(&this->dyna.actor, play)) {
|
||||||
switch (func_8002F368(play)) {
|
if (GameInteractor_Should(VB_SELL_POES_TO_POE_COLLECTOR, true, this)) {
|
||||||
case EXCH_ITEM_NONE:
|
switch (func_8002F368(play)) {
|
||||||
func_80A2F180(this);
|
case EXCH_ITEM_NONE:
|
||||||
this->actionFunc = func_80A2F94C;
|
func_80A2F180(this);
|
||||||
break;
|
this->actionFunc = func_80A2F94C;
|
||||||
case EXCH_ITEM_POE:
|
break;
|
||||||
player->actor.textId = 0x70F6;
|
case EXCH_ITEM_POE:
|
||||||
this->actionFunc = func_80A2F9C0;
|
player->actor.textId = 0x70F6;
|
||||||
break;
|
this->actionFunc = func_80A2F9C0;
|
||||||
case EXCH_ITEM_BIG_POE:
|
break;
|
||||||
player->actor.textId = 0x70F7;
|
case EXCH_ITEM_BIG_POE:
|
||||||
this->actionFunc = func_80A2FA50;
|
player->actor.textId = 0x70F7;
|
||||||
break;
|
this->actionFunc = func_80A2FA50;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ typedef struct EnGb {
|
||||||
/* 0x0388 */ EnGbCagedSoul cagedSouls[4];
|
/* 0x0388 */ EnGbCagedSoul cagedSouls[4];
|
||||||
} EnGb; // size = 0x0438
|
} EnGb; // size = 0x0438
|
||||||
|
|
||||||
void func_80A2FC0C(EnGb* actor, PlayState* play);
|
void func_80A2FB40(EnGb* actor, PlayState* play);
|
||||||
|
void func_80A2F83C(EnGb* actor, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -712,7 +712,7 @@ void EnPoField_SoulInteract(EnPoField* this, PlayState* play) {
|
||||||
if (this->actor.params == 0) {
|
if (this->actor.params == 0) {
|
||||||
Item_Give(play, ITEM_POE);
|
Item_Give(play, ITEM_POE);
|
||||||
this->actor.textId = 0x5008;
|
this->actor.textId = 0x5008;
|
||||||
} else {
|
} else if (GameInteractor_Should(VB_BOTTLE_BIG_POE, true, this)) {
|
||||||
this->actor.textId = 0x508F;
|
this->actor.textId = 0x508F;
|
||||||
Item_Give(play, ITEM_BIG_POE);
|
Item_Give(play, ITEM_BIG_POE);
|
||||||
Flags_SetSwitch(play, sEnPoFieldSpawnSwitchFlags[this->spawnFlagIndex]);
|
Flags_SetSwitch(play, sEnPoFieldSpawnSwitchFlags[this->spawnFlagIndex]);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue