mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-04-28 13:17:58 +03:00
Merge 3b2b91d860
into fbbfc07ff1
This commit is contained in:
commit
4ff84449be
19 changed files with 80 additions and 29 deletions
|
@ -294,6 +294,14 @@ typedef enum {
|
|||
// - `*ObjKibako2`
|
||||
VB_CRATE_SETUP_DRAW,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_CRAWL,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// !Flags_GetItemGetInf(ITEMGETINF_1C)
|
||||
|
|
|
@ -2097,6 +2097,7 @@ void StaticData::HintTable_Init_Item() {
|
|||
},
|
||||
{ CustomMessage("a master unlocker", /*german*/ "ein Meisterentsperrer", /*french*/ "un Kit de Déverrouillage") });
|
||||
// /*spanish*/un desbloqueador maestro
|
||||
hintTextTable[RHT_CRAWL] = HintText(CustomMessage("the ability to crawl", /*german*/"!!!", /*french*/"!!!"));
|
||||
|
||||
//RANDOTODO if these are ever used for anything other than name, they want abscure and ambiguous hints
|
||||
hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("an infinite Quiver", /*german*/"ein unendlicher Köcher", /*french*/"un Carquois Infini"));
|
||||
|
|
|
@ -591,6 +591,10 @@ void GenerateItemPool() {
|
|||
AddItemToMainPool(RG_PROGRESSIVE_SCALE);
|
||||
}
|
||||
|
||||
if (ctx->GetOption(RSK_SHUFFLE_CRAWL)) {
|
||||
AddItemToMainPool(RG_CRAWL);
|
||||
}
|
||||
|
||||
if (ctx->GetOption(RSK_SHUFFLE_BEEHIVES)) {
|
||||
// 32 total beehive locations
|
||||
AddItemToPool(PendingJunkPool, RG_RED_RUPEE, 23);
|
||||
|
|
|
@ -781,6 +781,9 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
|
|||
va_copy(args, originalArgs);
|
||||
|
||||
switch (id) {
|
||||
case VB_CRAWL:
|
||||
*should = !RAND_GET_OPTION(RSK_SHUFFLE_CRAWL) || Flags_GetRandomizerInf(RAND_INF_CAN_CRAWL);
|
||||
break;
|
||||
case VB_ALLOW_ENTRANCE_CS_FOR_EITHER_AGE: {
|
||||
s32 entranceIndex = va_arg(args, s32);
|
||||
|
||||
|
|
|
@ -352,6 +352,9 @@ void Rando::StaticData::InitItemTable() {
|
|||
itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
|
||||
itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale);
|
||||
|
||||
itemTable[RG_CRAWL] = Item(RG_CRAWL, Text{ "Crawl", "Ramper", "Kriechen" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_CRAWL, RG_CRAWL, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
|
||||
itemTable[RG_CRAWL].SetCustomDrawFunc(Randomizer_DrawBronzeScale);
|
||||
|
||||
itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
|
||||
itemTable[RG_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag);
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ void RegionTable_Init_BottomOfTheWell() {
|
|||
areaTable[RR_BOTTOM_OF_THE_WELL_ENTRYWAY] = Region("Bottom of the Well Entryway", "Bottom of the Well", {RA_BOTTOM_OF_THE_WELL}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
//Technically involves an fake wall, but passing it lensless is intended in vanilla and it is well telegraphed
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla() && logic->IsChild && logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsMQ() && logic->IsChild;}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla() && logic->CanUse(RG_CRAWL) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsMQ() && logic->CanUse(RG_CRAWL);}),
|
||||
Entrance(RR_KAK_WELL, []{return true;}),
|
||||
});
|
||||
|
||||
|
@ -33,12 +33,12 @@ void RegionTable_Init_BottomOfTheWell() {
|
|||
LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_POT, (logic->CanBreakPots() && logic->LoweredWaterInsideBotw) || logic->CanUse(RG_BOOMERANG)),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->IsChild && logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->CanUse(RG_CRAWL) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, []{return logic->CanUse(RG_CRAWL) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_COFFIN_ROOM, []{return logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM, []{return logic->LoweredWaterInsideBotw && logic->IsChild;}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM, []{return logic->LoweredWaterInsideBotw && logic->CanUse(RG_CRAWL);}),
|
||||
//Falling down into basement requires nothing, but falling down somewhere specific requires lens or lens trick
|
||||
//kinda questionable given several drops are blocked by rocks, but that's how it was handled before and on N64
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return true;}),
|
||||
|
@ -80,7 +80,7 @@ void RegionTable_Init_BottomOfTheWell() {
|
|||
LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_POT_1, logic->CanBreakPots() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->CanUse(RG_CRAWL) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_LIKE_LIKE_CAGE, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}),
|
||||
//not sure if this lens check is needed, these holes are a bit too easy to find, but it matches existing logic
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}),
|
||||
|
@ -126,7 +126,7 @@ void RegionTable_Init_BottomOfTheWell() {
|
|||
}, {
|
||||
//Exits
|
||||
//This assumes we spawned in dead hand's room, if whatever trick made this relevant instead puts us in the previous room, remove the kill Dead Hand check.
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->IsChild && logic->CanKillEnemy(RE_DEAD_HAND);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->CanUse(RG_CRAWL) && logic->CanKillEnemy(RE_DEAD_HAND);}),
|
||||
});
|
||||
|
||||
areaTable[RR_BOTTOM_OF_THE_WELL_BASEMENT] = Region("Bottom of the Well Basement", "Bottom of the Well", {RA_BOTTOM_OF_THE_WELL}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
|
@ -159,7 +159,7 @@ void RegionTable_Init_BottomOfTheWell() {
|
|||
LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_9, logic->CanCutShrubs() && logic->BlastOrSmash()),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, []{return logic->IsChild && logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, []{return logic->CanUse(RG_CRAWL) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
|
||||
//It's possible to abuse boulder's limited range of collision detection to detonate the flowers through the boulder with bow, but this is a glitch
|
||||
//the exact range is just past the furthest away plank in the green goo section
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS, []{return Here(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || (logic->CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_BASEMENT));});}),
|
||||
|
@ -206,11 +206,11 @@ void RegionTable_Init_BottomOfTheWell() {
|
|||
LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BOMB_RIGHT_HEART, logic->HasExplosives()),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->IsChild;}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->CanUse(RG_CRAWL);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_WEST_ROOM_SWITCH, []{return Here(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE)) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_LOCKED_CAGE, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2) && logic->CanUseProjectile();}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_ROOM, []{return logic->IsChild && logic->LoweredWaterInsideBotw;}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_LOCKED_CAGE, []{return logic->CanUse(RG_CRAWL) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2) && logic->CanUseProjectile();}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_ROOM, []{return logic->CanUse(RG_CRAWL) && logic->LoweredWaterInsideBotw;}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, []{return logic->CanUse(RG_ZELDAS_LULLABY);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT, []{return true;}),
|
||||
});
|
||||
|
@ -240,7 +240,7 @@ void RegionTable_Init_BottomOfTheWell() {
|
|||
EventAccess(&logic->OpenedMiddleHoleMQBotw, []{return logic->HasExplosives();}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->CanUse(RG_CRAWL) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}),
|
||||
});
|
||||
|
||||
areaTable[RR_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_ROOM] = Region("Bottom of the Well MQ Dead Hand Room", "Bottom of the Well", {RA_BOTTOM_OF_THE_WELL}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
|
@ -254,7 +254,7 @@ void RegionTable_Init_BottomOfTheWell() {
|
|||
}, {
|
||||
//Exits
|
||||
//This assumes we spawned in dead hand's room, if whatever trick made this relevant instead puts us in the previous room, remove the kill Dead Hand check.
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->IsChild && logic->CanKillEnemy(RE_DEAD_HAND);}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->CanUse(RG_CRAWL) && logic->CanKillEnemy(RE_DEAD_HAND);}),
|
||||
});
|
||||
|
||||
areaTable[RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE] = Region("Bottom of the Well MQ Middle", "Bottom of the Well", {RA_BOTTOM_OF_THE_WELL}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
|
|
|
@ -149,7 +149,7 @@ void RegionTable_Init_DekuTree() {
|
|||
//Exits
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_TORCH_ROOM, []{return true;}),
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_BACK_ROOM, []{return Here(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, []{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);}) && Here(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, []{return logic->BlastOrSmash();});}),
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_UPPER, []{return Here(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, []{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);}) && logic->IsChild;}),
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_UPPER, []{return Here(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, []{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);}) && logic->CanUse(RG_CRAWL);}),
|
||||
});
|
||||
|
||||
areaTable[RR_DEKU_TREE_BASEMENT_BACK_ROOM] = Region("Deku Tree Basement Back Room", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
|
@ -167,7 +167,7 @@ void RegionTable_Init_DekuTree() {
|
|||
}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return true;}),
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, []{return logic->IsChild;}),
|
||||
Entrance(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, []{return logic->CanUse(RG_CRAWL);}),
|
||||
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return Here(RR_DEKU_TREE_BASEMENT_UPPER, []{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_DEKU_B1_BOW_WEBS) && logic->IsAdult && logic->CanUse(RG_FAIRY_BOW));});}),
|
||||
});
|
||||
|
||||
|
@ -384,7 +384,7 @@ void RegionTable_Init_DekuTree() {
|
|||
LOCATION(RC_DEKU_TREE_MQ_BASEMENT_GRAVES_GRASS_5, logic->CanCutShrubs()),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, []{return logic->IsChild && Here(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, []{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);});}),
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, []{return logic->CanUse(RG_CRAWL) && Here(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, []{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);});}),
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM, []{return true;}),
|
||||
//Using a bow to get past here as adult is a bit precise on standing position but simple, doing as as child requires a side-hop with the bow out to shoot through the torch and may be trick worthy
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM, []{return Here(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, []{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);});}),
|
||||
|
@ -412,7 +412,7 @@ void RegionTable_Init_DekuTree() {
|
|||
LOCATION(RC_DEKU_TREE_MQ_BASEMENT_UPPER_GRASS_3, logic->CanCutShrubs()),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, []{return logic->IsChild;}),
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, []{return logic->CanUse(RG_CRAWL);}),
|
||||
Entrance(RR_DEKU_TREE_MQ_BASEMENT, []{return true;}),
|
||||
//If strength 0 is shuffled, add hovers or block push to the stick check
|
||||
//recoiling to skip swim is possible, but would be a trick
|
||||
|
|
|
@ -23,7 +23,7 @@ void RegionTable_Init_SpiritTemple() {
|
|||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_CHILD, []{return logic->IsChild;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_CHILD, []{return logic->CanUse(RG_CRAWL);}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_EARLY_ADULT, []{return logic->CanUse(RG_SILVER_GAUNTLETS);}),
|
||||
});
|
||||
|
||||
|
@ -43,7 +43,7 @@ void RegionTable_Init_SpiritTemple() {
|
|||
LOCATION(RC_SPIRIT_TEMPLE_BEFORE_CHILD_CLIMB_SMALL_CRATE_2, logic->CanBreakSmallCrates()),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_CHILD_CLIMB, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_CHILD_CLIMB, []{return logic->CanUse(RG_CRAWL) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}),
|
||||
});
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Region("Child Spirit Temple Climb", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
|
@ -165,7 +165,7 @@ void RegionTable_Init_SpiritTemple() {
|
|||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->IsChild;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->CanUse(RG_CRAWL);}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH, []{return logic->CanUse(RG_LONGSHOT) && logic->CanUse(RG_BOMBCHU_5);}),
|
||||
});
|
||||
|
||||
|
@ -183,7 +183,7 @@ void RegionTable_Init_SpiritTemple() {
|
|||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_SOUTH, []{return Here(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->CanKillEnemy(RE_TORCH_SLUG);});}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH, []{return Here(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->CanKillEnemy(RE_TORCH_SLUG);});}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, []{return logic->IsChild && logic->MQSpiritCrawlBoulder;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, []{return logic->CanUse(RG_CRAWL) && logic->MQSpiritCrawlBoulder;}),
|
||||
});
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_SOUTH] = Region("Spirit Temple MQ 1F Gibdo Room South", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
|
@ -249,7 +249,7 @@ void RegionTable_Init_SpiritTemple() {
|
|||
EventAccess(&logic->MQSpiritCrawlBoulder, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->IsChild && logic->MQSpiritCrawlBoulder;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->CanUse(RG_CRAWL) && logic->MQSpiritCrawlBoulder;}),
|
||||
//This tracks possible child access, if adult has not entered STATUE_ROOM. Certain Child Access is checked for separately as 7 Keys
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}),
|
||||
});
|
||||
|
|
|
@ -34,8 +34,8 @@ void RegionTable_Init_CastleGrounds() {
|
|||
}, {
|
||||
//Exits
|
||||
Entrance(RR_CASTLE_GROUNDS, []{return true;}),
|
||||
Entrance(RR_HC_GARDEN, []{return logic->CanUse(RG_WEIRD_EGG) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}),
|
||||
Entrance(RR_HC_GREAT_FAIRY_FOUNTAIN, []{return logic->BlastOrSmash();}),
|
||||
Entrance(RR_HC_GARDEN, []{return logic->CanUse(RG_CRAWL) && (logic->CanUse(RG_WEIRD_EGG) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash()));}),
|
||||
Entrance(RR_HC_GREAT_FAIRY_FOUNTAIN, []{return logic->CanUse(RG_CRAWL) && logic->BlastOrSmash();}),
|
||||
Entrance(RR_HC_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}),
|
||||
});
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ void RegionTable_Init_KokiriForest() {
|
|||
EventAccess(&logic->ShowedMidoSwordAndShield, []{return logic->ShowedMidoSwordAndShield || (logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD));}),
|
||||
}, {
|
||||
//Locations
|
||||
LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild),
|
||||
LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->CanUse(RG_CRAWL)),
|
||||
LOCATION(RC_KF_GS_KNOW_IT_ALL_HOUSE, logic->IsChild && logic->CanAttack() && (/*TODO: HasNightStart ||*/ logic->CanLeaveForest() || logic->CanUse(RG_SUNS_SONG)) && logic->CanGetNightTimeGS()),
|
||||
LOCATION(RC_KF_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanAttack()),
|
||||
LOCATION(RC_KF_GS_HOUSE_OF_TWINS, logic->IsAdult && (logic->HookshotOrBoomerang() || (ctx->GetTrickOption(RT_KF_ADULT_GS) && logic->CanUse(RG_HOVER_BOOTS))) && logic->CanGetNightTimeGS()),
|
||||
|
@ -27,8 +27,8 @@ void RegionTable_Init_KokiriForest() {
|
|||
LOCATION(RC_KF_SOUTH_GRASS_EAST_RUPEE, logic->IsChild),
|
||||
LOCATION(RC_KF_NORTH_GRASS_WEST_RUPEE, logic->IsChild),
|
||||
LOCATION(RC_KF_NORTH_GRASS_EAST_RUPEE, logic->IsChild),
|
||||
LOCATION(RC_KF_BOULDER_RUPEE_1, logic->IsChild),
|
||||
LOCATION(RC_KF_BOULDER_RUPEE_2, logic->IsChild),
|
||||
LOCATION(RC_KF_BOULDER_RUPEE_1, logic->CanUse(RG_CRAWL)),
|
||||
LOCATION(RC_KF_BOULDER_RUPEE_2, logic->CanUse(RG_CRAWL)),
|
||||
LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))),
|
||||
LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))),
|
||||
LOCATION(RC_KF_BEAN_RUPEE_3, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))),
|
||||
|
|
|
@ -55,7 +55,7 @@ void RegionTable_Init_LonLonRanch() {
|
|||
|
||||
areaTable[RR_LLR_TOWER] = Region("LLR Tower", "LLR Tower", {}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LOCATION(RC_LLR_FREESTANDING_POH, logic->IsChild),
|
||||
LOCATION(RC_LLR_FREESTANDING_POH, logic->IsChild && logic->HasItem(RG_CRAWL)),
|
||||
LOCATION(RC_LLR_TOWER_LEFT_COW, logic->CanUse(RG_EPONAS_SONG)),
|
||||
LOCATION(RC_LLR_TOWER_RIGHT_COW, logic->CanUse(RG_EPONAS_SONG)),
|
||||
}, {
|
||||
|
|
|
@ -221,6 +221,8 @@ bool Logic::HasItem(RandomizerGet itemName) {
|
|||
return CurrentUpgrade(UPG_SCALE) >= 1;
|
||||
case RG_GOLDEN_SCALE:
|
||||
return CurrentUpgrade(UPG_SCALE) >= 2;
|
||||
case RG_CRAWL:
|
||||
return CheckRandoInf(RAND_INF_CAN_CRAWL);
|
||||
case RG_POCKET_EGG:
|
||||
return CheckRandoInf(RAND_INF_ADULT_TRADES_HAS_POCKET_EGG);
|
||||
case RG_COJIRO:
|
||||
|
@ -376,6 +378,8 @@ bool Logic::CanUse(RandomizerGet itemName) {
|
|||
return HasItem(RG_CHILD_WALLET); // as long as you have enough rubies
|
||||
case RG_EPONA:
|
||||
return IsAdult && CanUse(RG_EPONAS_SONG);
|
||||
case RG_CRAWL:
|
||||
return IsChild;
|
||||
|
||||
// Bottle Items
|
||||
case RG_BOTTLE_WITH_BUGS:
|
||||
|
@ -1625,6 +1629,9 @@ void Logic::ApplyItemEffect(Item& item, bool state) {
|
|||
case RG_CLAIM_CHECK:
|
||||
SetRandoInf(randoGet - RG_COJIRO + RAND_INF_ADULT_TRADES_HAS_COJIRO, state);
|
||||
break;
|
||||
case RG_CRAWL:
|
||||
SetRandoInf(RAND_INF_CAN_CRAWL, state);
|
||||
break;
|
||||
case RG_PROGRESSIVE_HOOKSHOT: {
|
||||
uint8_t i;
|
||||
for (i = 0; i < 3; i++) {
|
||||
|
@ -2388,6 +2395,11 @@ void Logic::Reset() {
|
|||
SetRandoInf(RAND_INF_CAN_SWIM, true);
|
||||
}
|
||||
|
||||
// If we're not shuffling crawl, we start with it
|
||||
if (ctx->GetOption(RSK_SHUFFLE_CRAWL).Is(false)) {
|
||||
SetRandoInf(RAND_INF_CAN_CRAWL, true);
|
||||
}
|
||||
|
||||
// If we're not shuffling child's wallet, we start with it
|
||||
if (ctx->GetOption(RSK_SHUFFLE_CHILD_WALLET).Is(false)) {
|
||||
SetRandoInf(RAND_INF_HAS_WALLET, true);
|
||||
|
|
|
@ -247,6 +247,7 @@ void Settings::CreateOptionDescriptions() {
|
|||
"\n"
|
||||
"If you enter a water entrance without swim you will be respawned on land to prevent infinite death loops.\n"
|
||||
"If you void out in Water Temple you will immediately be kicked out to prevent a softlock.";
|
||||
mOptionDescriptions[RSK_SHUFFLE_CRAWL] = "Shuffles the ability to use crawlspaces into the item pool.";
|
||||
mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG] = "Shuffles the Weird Egg from Malon in to the item pool. Enabling "
|
||||
"\"Skip Child Zelda\" disables this feature.\n"
|
||||
"\n"
|
||||
|
|
|
@ -5165,7 +5165,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) {
|
|||
void Randomizer::CreateCustomMessages() {
|
||||
// RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED
|
||||
// with GIMESSAGE(getItemID, itemID, english, german, french).
|
||||
const std::array<GetItemMessage, 112> getItemMessages = { {
|
||||
const std::array<GetItemMessage, 113> getItemMessages = { {
|
||||
GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn wirklich gefunden!",
|
||||
"Félicitation! Vous avez trouvé %gGreg%w!"),
|
||||
GIMESSAGE(RG_MASTER_SWORD, ITEM_SWORD_MASTER, "You found the %gMaster Sword%w!",
|
||||
|
@ -5493,6 +5493,9 @@ void Randomizer::CreateCustomMessages() {
|
|||
GIMESSAGE(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!",
|
||||
"Du hast die %rBronzene Schuppe%w erhalten!&Die Macht der Schwungkraft ist dein!",
|
||||
"Vous obtenez l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est&à vous!"),
|
||||
GIMESSAGE_NO_GERMAN(RG_CRAWL, ITEM_SCALE_SILVER,
|
||||
"You got the %rAbility to Crawl%w!&The power of kneecaps is yours!",
|
||||
"Vous obtenez la %rCapacité à Ramper%w!"),
|
||||
GIMESSAGE(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!",
|
||||
"Du hast eine verlorene %rAngelrute%w gefunden!&Zeit, im Teich zu angeln!",
|
||||
"Vous obtenez une %rCanne à pêche%w&perdue!&Il est temps d'aller à %gl'étang%w!"),
|
||||
|
@ -5604,6 +5607,7 @@ extern "C" u8 Return_Item_Entry(GetItemEntry itemEntry, u8 returnItem);
|
|||
std::map<RandomizerGet, RandomizerInf> randomizerGetToRandInf = {
|
||||
{ RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND },
|
||||
{ RG_BRONZE_SCALE, RAND_INF_CAN_SWIM },
|
||||
{ RG_CRAWL, RAND_INF_CAN_CRAWL },
|
||||
{ RG_QUIVER_INF, RAND_INF_HAS_INFINITE_QUIVER },
|
||||
{ RG_BOMB_BAG_INF, RAND_INF_HAS_INFINITE_BOMB_BAG },
|
||||
{ RG_BULLET_BAG_INF, RAND_INF_HAS_INFINITE_BULLET_BAG },
|
||||
|
|
|
@ -3956,6 +3956,7 @@ typedef enum {
|
|||
RG_HINT,
|
||||
RG_TYCOON_WALLET,
|
||||
RG_BRONZE_SCALE,
|
||||
RG_CRAWL,
|
||||
RG_CHILD_WALLET,
|
||||
RG_BOMBCHU_BAG,
|
||||
RG_QUIVER_INF,
|
||||
|
@ -5153,6 +5154,7 @@ typedef enum {
|
|||
RHT_OCARINA_C_LEFT_BUTTON,
|
||||
RHT_OCARINA_C_RIGHT_BUTTON,
|
||||
RHT_BRONZE_SCALE,
|
||||
RHT_CRAWL,
|
||||
RHT_FISHING_POLE,
|
||||
RHT_SKELETON_KEY,
|
||||
RHT_EPONA,
|
||||
|
@ -5700,6 +5702,7 @@ typedef enum {
|
|||
RSK_SHUFFLE_OCARINA,
|
||||
RSK_SHUFFLE_OCARINA_BUTTONS,
|
||||
RSK_SHUFFLE_SWIM,
|
||||
RSK_SHUFFLE_CRAWL,
|
||||
RSK_STARTING_DEKU_SHIELD,
|
||||
RSK_STARTING_KOKIRI_SWORD,
|
||||
RSK_STARTING_MASTER_SWORD,
|
||||
|
|
|
@ -1002,6 +1002,7 @@ typedef enum {
|
|||
RAND_INF_CAUGHT_LOACH,
|
||||
|
||||
RAND_INF_CAN_SWIM,
|
||||
RAND_INF_CAN_CRAWL,
|
||||
|
||||
RAND_INF_HAS_WALLET,
|
||||
|
||||
|
|
|
@ -256,6 +256,10 @@ extern "C" void Randomizer_InitSaveFile() {
|
|||
Flags_SetRandomizerInf(RAND_INF_CAN_SWIM);
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_CRAWL) == RO_GENERIC_OFF) {
|
||||
Flags_SetRandomizerInf(RAND_INF_CAN_CRAWL);
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHILD_WALLET) == RO_GENERIC_OFF) {
|
||||
Flags_SetRandomizerInf(RAND_INF_HAS_WALLET);
|
||||
}
|
||||
|
|
|
@ -211,6 +211,7 @@ void Settings::CreateOptions() {
|
|||
OPT_BOOL(RSK_SHUFFLE_OCARINA, "Shuffle Ocarinas", CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), mOptionDescriptions[RSK_SHUFFLE_OCARINA]);
|
||||
OPT_BOOL(RSK_SHUFFLE_OCARINA_BUTTONS, "Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]);
|
||||
OPT_BOOL(RSK_SHUFFLE_SWIM, "Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]);
|
||||
OPT_BOOL(RSK_SHUFFLE_CRAWL, "Shuffle Crawl", CVAR_RANDOMIZER_SETTING("ShuffleCrawl"), mOptionDescriptions[RSK_SHUFFLE_CRAWL]);
|
||||
OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]);
|
||||
OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
|
||||
OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WidgetType::Combobox, RO_SHUFFLE_POTS_OFF);
|
||||
|
@ -1214,6 +1215,7 @@ void Settings::CreateOptions() {
|
|||
&mOptions[RSK_SHUFFLE_OCARINA],
|
||||
&mOptions[RSK_SHUFFLE_OCARINA_BUTTONS],
|
||||
&mOptions[RSK_SHUFFLE_SWIM],
|
||||
&mOptions[RSK_SHUFFLE_CRAWL],
|
||||
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
|
||||
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
|
||||
&mOptions[RSK_SHUFFLE_FISHING_POLE],
|
||||
|
@ -1491,6 +1493,7 @@ void Settings::CreateOptions() {
|
|||
&mOptions[RSK_SHUFFLE_OCARINA],
|
||||
&mOptions[RSK_SHUFFLE_OCARINA_BUTTONS],
|
||||
&mOptions[RSK_SHUFFLE_SWIM],
|
||||
&mOptions[RSK_SHUFFLE_CRAWL],
|
||||
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
|
||||
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
|
||||
&mOptions[RSK_SHUFFLE_MERCHANTS],
|
||||
|
|
|
@ -7629,6 +7629,10 @@ s32 Player_TryEnteringCrawlspace(Player* this, PlayState* play, u32 interactWall
|
|||
s32 i;
|
||||
|
||||
if (!LINK_IS_ADULT && !(this->stateFlags1 & PLAYER_STATE1_IN_WATER) && (interactWallFlags & 0x30)) {
|
||||
if (!GameInteractor_Should(VB_CRAWL, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wallPoly = this->actor.wallPoly;
|
||||
CollisionPoly_GetVerticesByBgId(wallPoly, this->actor.wallBgId, &play->colCtx, wallVertices);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue