Merge pull request #6446 from HarbourMasters/develop-ackbar
merge develop-ackbar into develop
This commit is contained in:
@@ -17,10 +17,10 @@ static void RegisterBossDefeatTimestamps() {
|
||||
BOSS_DEFEAT_TIMESTAMP(ACTOR_BOSS_SST, TIMESTAMP_DEFEAT_BONGO_BONGO);
|
||||
BOSS_DEFEAT_TIMESTAMP(ACTOR_BOSS_TW, TIMESTAMP_DEFEAT_TWINROVA);
|
||||
BOSS_DEFEAT_TIMESTAMP(ACTOR_BOSS_GANON, TIMESTAMP_DEFEAT_GANONDORF);
|
||||
BOSS_DEFEAT_TIMESTAMP(ACTOR_BOSS_GANON2, TIMESTAMP_DEFEAT_GANON);
|
||||
|
||||
COND_ID_HOOK(OnBossDefeat, ACTOR_BOSS_GANON2, true,
|
||||
[](void* refActor) { gSaveContext.ship.stats.gameComplete = true; });
|
||||
COND_ID_HOOK(OnBossDefeat, ACTOR_BOSS_GANON2, true, [](void* refActor) {
|
||||
gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] = GAMEPLAYSTAT_TOTAL_TIME;
|
||||
gSaveContext.ship.stats.gameComplete = true;
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterBossDefeatTimestamps);
|
||||
|
||||
@@ -2,11 +2,17 @@
|
||||
|
||||
extern "C" {
|
||||
#include <variables.h>
|
||||
extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
// RANDOTODO: Port the rest of the behavior for this enhancement here.
|
||||
|
||||
void BuildNightGuardMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
||||
// Other guards should not have their text overridden
|
||||
if (gPlayState->sceneNum != SCENE_MARKET_ENTRANCE_NIGHT) {
|
||||
return;
|
||||
}
|
||||
|
||||
CustomMessage msg = CustomMessage("You look bored. Wanna go out for a walk?\x1B%gYes&No%w",
|
||||
"Du siehst gelangweilt aus. Willst Du einen Spaziergang machen?\x1B%gJa&Nein%w",
|
||||
"Tu as l'air de t'ennuyer. Tu veux aller faire un tour?\x1B%gOui&Non%w");
|
||||
|
||||
@@ -225,6 +225,9 @@ class GameInteractor {
|
||||
static GameInteractionEffectQueryResult RemoveEffect(RemovableGameInteractionEffect& effect);
|
||||
|
||||
// Game Hooks
|
||||
//
|
||||
// Hooks should be idempotent and execution order is not guaranteed.
|
||||
// If two operations must happen in a specific order, they should be placed in the same hook.
|
||||
HOOK_ID nextHookId = 1;
|
||||
|
||||
template <typename H> struct RegisteredGameHooks {
|
||||
|
||||
@@ -1371,6 +1371,14 @@ typedef enum {
|
||||
// - `*DoorShutter`
|
||||
VB_LOCK_BOSS_DOOR,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*EnMs`
|
||||
VB_MAGIC_BEAN_SALESMAN_TAKE_MONEY,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// CHECK_QUEST_ITEM(QUEST_SONG_EPONA)
|
||||
|
||||
@@ -149,6 +149,7 @@ static void PlaceItemsForType(RandomizerCheckType rctype, bool overworldActive =
|
||||
void GenerateItemPool() {
|
||||
// RANDOTODO proper removal of items not in pool or logically relevant instead of dummy checks.
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
ctx->possibleIceTrapModels.clear();
|
||||
itemPool.clear();
|
||||
junkPool.clear();
|
||||
plentifulPool.clear();
|
||||
|
||||
@@ -49,9 +49,9 @@ void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) {
|
||||
"I never thought I'd say this, but I'm selling the last %rMagic Bean%w.^%y99 Rupees%w, no "
|
||||
"less.\x1B%gYes&No%w",
|
||||
"Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^%rWundererbse%w für %y99 "
|
||||
"Rubine%w.\x1B&%gJa&Nein%w",
|
||||
"Je te vends mon dernier %rHaricot&magique%g pour %y99 Rubis%w.\x1B&%gAcheterNe pas acheter%w");
|
||||
msg.Format();
|
||||
"Rubine%w.\x1B%gJa&Nein%w",
|
||||
"Je te vends mon dernier %rHaricot&magique%w pour %y99 Rubis%w.\x1B%gAcheter&Ne pas acheter%w");
|
||||
msg.AutoFormat();
|
||||
} else if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_10) {
|
||||
msg = CustomMessage("Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w",
|
||||
"Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <libultraship/libultra.h>
|
||||
#include "global.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
#include "item_category_adj.h"
|
||||
|
||||
extern "C" {
|
||||
#include "variables.h"
|
||||
@@ -35,24 +36,7 @@ extern "C" void ObjKibako2_RandomizerDraw(Actor* thisx, PlayState* play) {
|
||||
|
||||
GetItemEntry crateItem =
|
||||
Rando::Context::GetInstance()->GetFinalGIEntry(crateIdentity->randomizerCheck, true, GI_NONE);
|
||||
getItemCategory = crateItem.getItemCategory;
|
||||
|
||||
// If they have bombchus, don't consider the bombchu item major
|
||||
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU &&
|
||||
((crateItem.modIndex == MOD_RANDOMIZER && crateItem.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) ||
|
||||
(crateItem.modIndex == MOD_NONE &&
|
||||
(crateItem.getItemId == GI_BOMBCHUS_5 || crateItem.getItemId == GI_BOMBCHUS_10 ||
|
||||
crateItem.getItemId == GI_BOMBCHUS_20)))) {
|
||||
getItemCategory = ITEM_CATEGORY_JUNK;
|
||||
// If it's a bottle and they already have one, consider the item lesser
|
||||
} else if ((crateItem.modIndex == MOD_RANDOMIZER && crateItem.getItemId >= RG_BOTTLE_WITH_RED_POTION &&
|
||||
crateItem.getItemId <= RG_BOTTLE_WITH_POE) ||
|
||||
(crateItem.modIndex == MOD_NONE &&
|
||||
(crateItem.getItemId == GI_BOTTLE || crateItem.getItemId == GI_MILK_BOTTLE))) {
|
||||
if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) {
|
||||
getItemCategory = ITEM_CATEGORY_LESSER;
|
||||
}
|
||||
}
|
||||
getItemCategory = Randomizer_AdjustItemCategory(crateItem);
|
||||
|
||||
// Change texture
|
||||
switch (getItemCategory) {
|
||||
@@ -102,24 +86,7 @@ extern "C" void ObjKibako_RandomizerDraw(Actor* thisx, PlayState* play) {
|
||||
|
||||
GetItemEntry smallCrateItem =
|
||||
Rando::Context::GetInstance()->GetFinalGIEntry(crateIdentity->randomizerCheck, true, GI_NONE);
|
||||
getItemCategory = smallCrateItem.getItemCategory;
|
||||
|
||||
// If they have bombchus, don't consider the bombchu item major
|
||||
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU &&
|
||||
((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) ||
|
||||
(smallCrateItem.modIndex == MOD_NONE &&
|
||||
(smallCrateItem.getItemId == GI_BOMBCHUS_5 || smallCrateItem.getItemId == GI_BOMBCHUS_10 ||
|
||||
smallCrateItem.getItemId == GI_BOMBCHUS_20)))) {
|
||||
getItemCategory = ITEM_CATEGORY_JUNK;
|
||||
// If it's a bottle and they already have one, consider the item lesser
|
||||
} else if ((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId >= RG_BOTTLE_WITH_RED_POTION &&
|
||||
smallCrateItem.getItemId <= RG_BOTTLE_WITH_POE) ||
|
||||
(smallCrateItem.modIndex == MOD_NONE &&
|
||||
(smallCrateItem.getItemId == GI_BOTTLE || smallCrateItem.getItemId == GI_MILK_BOTTLE))) {
|
||||
if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) {
|
||||
getItemCategory = ITEM_CATEGORY_LESSER;
|
||||
}
|
||||
}
|
||||
getItemCategory = Randomizer_AdjustItemCategory(smallCrateItem);
|
||||
|
||||
// Change texture
|
||||
switch (getItemCategory) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <soh/OTRGlobals.h>
|
||||
#include "soh_assets.h"
|
||||
#include "static_data.h"
|
||||
#include "item_category_adj.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -38,7 +39,7 @@ extern "C" void EnKusa_RandomizerDraw(Actor* thisx, PlayState* play) {
|
||||
if (csmc && (!requiresStoneAgony || (requiresStoneAgony && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) {
|
||||
auto itemEntry =
|
||||
Rando::Context::GetInstance()->GetFinalGIEntry(grassIdentity->randomizerCheck, true, GI_NONE);
|
||||
GetItemCategory getItemCategory = itemEntry.getItemCategory;
|
||||
GetItemCategory getItemCategory = Randomizer_AdjustItemCategory(itemEntry);
|
||||
|
||||
switch (getItemCategory) {
|
||||
case ITEM_CATEGORY_JUNK:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh_assets.h"
|
||||
#include "static_data.h"
|
||||
#include "item_category_adj.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -28,7 +29,7 @@ extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) {
|
||||
if (csmc && (!requiresStoneAgony || (requiresStoneAgony && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) {
|
||||
auto itemEntry =
|
||||
Rando::Context::GetInstance()->GetFinalGIEntry(potIdentity->randomizerCheck, true, GI_NONE);
|
||||
GetItemCategory getItemCategory = itemEntry.getItemCategory;
|
||||
GetItemCategory getItemCategory = Randomizer_AdjustItemCategory(itemEntry);
|
||||
|
||||
switch (getItemCategory) {
|
||||
case ITEM_CATEGORY_LESSER:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "soh_assets.h"
|
||||
#include "static_data.h"
|
||||
#include "soh/ObjectExtension/ObjectExtension.h"
|
||||
#include "item_category_adj.h"
|
||||
|
||||
extern "C" {
|
||||
#include "variables.h"
|
||||
@@ -60,24 +61,7 @@ extern "C" void EnWood02_RandomizerDraw(Actor* thisx, PlayState* play) {
|
||||
getItemCategory = ITEM_CATEGORY_JUNK;
|
||||
} else {
|
||||
treeItem = Rando::Context::GetInstance()->GetFinalGIEntry(treeIdentity->randomizerCheck, true, GI_NONE);
|
||||
getItemCategory = treeItem.getItemCategory;
|
||||
|
||||
// If they have bombchus, don't consider the bombchu item major
|
||||
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU &&
|
||||
((treeItem.modIndex == MOD_RANDOMIZER && treeItem.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) ||
|
||||
(treeItem.modIndex == MOD_NONE &&
|
||||
(treeItem.getItemId == GI_BOMBCHUS_5 || treeItem.getItemId == GI_BOMBCHUS_10 ||
|
||||
treeItem.getItemId == GI_BOMBCHUS_20)))) {
|
||||
getItemCategory = ITEM_CATEGORY_JUNK;
|
||||
// If it's a bottle and they already have one, consider the item lesser
|
||||
} else if ((treeItem.modIndex == MOD_RANDOMIZER && treeItem.getItemId >= RG_BOTTLE_WITH_RED_POTION &&
|
||||
treeItem.getItemId <= RG_BOTTLE_WITH_POE) ||
|
||||
(treeItem.modIndex == MOD_NONE &&
|
||||
(treeItem.getItemId == GI_BOTTLE || treeItem.getItemId == GI_MILK_BOTTLE))) {
|
||||
if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) {
|
||||
getItemCategory = ITEM_CATEGORY_LESSER;
|
||||
}
|
||||
}
|
||||
getItemCategory = Randomizer_AdjustItemCategory(treeItem);
|
||||
}
|
||||
|
||||
GraphicsContext* gfxCtx = play->state.gfxCtx;
|
||||
|
||||
@@ -980,6 +980,15 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
|
||||
OTRGlobals::Instance->gRandoContext->GetItemLocation(RC_ZR_MAGIC_BEAN_SALESMAN)->GetPrice();
|
||||
} else if (RAND_GET_OPTION(RSK_SKIP_PLANTING_BEANS)) {
|
||||
*should = gSaveContext.rupees >= 60;
|
||||
} else if (BEANS_BOUGHT == 9) {
|
||||
*should = gSaveContext.rupees >= 99;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VB_MAGIC_BEAN_SALESMAN_TAKE_MONEY: {
|
||||
if (BEANS_BOUGHT == 9) {
|
||||
Rupees_ChangeBy(-99);
|
||||
*should = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
28
soh/soh/Enhancements/randomizer/item_category_adj.cpp
Normal file
28
soh/soh/Enhancements/randomizer/item_category_adj.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <stdint.h>
|
||||
#include "item_category_adj.h"
|
||||
#include "z64item.h"
|
||||
#include "variables.h"
|
||||
#include "macros.h"
|
||||
|
||||
GetItemCategory Randomizer_AdjustItemCategory(GetItemEntry item) {
|
||||
GetItemCategory category = item.getItemCategory;
|
||||
|
||||
// Downgrade bombchus to lesser if the player already has bombchus
|
||||
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU &&
|
||||
((item.modIndex == MOD_RANDOMIZER && item.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) ||
|
||||
(item.modIndex == MOD_NONE &&
|
||||
(item.getItemId == GI_BOMBCHUS_5 || item.getItemId == GI_BOMBCHUS_10 || item.getItemId == GI_BOMBCHUS_20)))) {
|
||||
category = ITEM_CATEGORY_LESSER;
|
||||
}
|
||||
|
||||
// Downgrade bottles to lesser if the player already has a bottle
|
||||
if ((item.modIndex == MOD_RANDOMIZER && item.getItemId >= RG_BOTTLE_WITH_RED_POTION &&
|
||||
item.getItemId <= RG_BOTTLE_WITH_POE) ||
|
||||
(item.modIndex == MOD_NONE && (item.getItemId == GI_BOTTLE || item.getItemId == GI_MILK_BOTTLE))) {
|
||||
if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) {
|
||||
category = ITEM_CATEGORY_LESSER;
|
||||
}
|
||||
}
|
||||
|
||||
return category;
|
||||
}
|
||||
18
soh/soh/Enhancements/randomizer/item_category_adj.h
Normal file
18
soh/soh/Enhancements/randomizer/item_category_adj.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef ITEM_CATEGORY_ADJ_H
|
||||
#define ITEM_CATEGORY_ADJ_H
|
||||
|
||||
#include "../item-tables/ItemTableTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
GetItemCategory Randomizer_AdjustItemCategory(GetItemEntry item);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -244,7 +244,7 @@ void RegionTable_Init_DekuTree() {
|
||||
}, {
|
||||
//Locations
|
||||
LOCATION(RC_DEKU_TREE_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)),
|
||||
LOCATION(RC_DEKU_TREE_MQ_GS_LOBBY, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)),
|
||||
LOCATION(RC_DEKU_TREE_MQ_GS_LOBBY, (logic->CanBreakCrates() || ctx->GetTrickOption(RT_VISIBLE_COLLISION)) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)),
|
||||
LOCATION(RC_DEKU_TREE_MQ_LOBBY_HEART, true),
|
||||
LOCATION(RC_DEKU_TREE_MQ_2F_GRASS_1, logic->CanCutShrubs()),
|
||||
LOCATION(RC_DEKU_TREE_MQ_2F_GRASS_2, logic->CanCutShrubs()),
|
||||
|
||||
@@ -725,7 +725,7 @@ void RegionTable_Init_FireTemple() {
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_MQ_MAZE_CRATE_CAGE] = Region("Fire Temple MQ Maze Crate Cage", SCENE_FIRE_TEMPLE, {}, {
|
||||
//Locations
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)),
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST) && (ctx->GetTrickOption(RT_VISIBLE_COLLISION) || logic->CanBreakCrates())),
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_1, logic->CanBreakCrates()),
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_2, logic->CanBreakCrates()),
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_3, logic->CanBreakCrates()),
|
||||
@@ -739,9 +739,8 @@ void RegionTable_Init_FireTemple() {
|
||||
areaTable[RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE] = Region("Fire Temple MQ Upper Lizalfos Maze", SCENE_FIRE_TEMPLE, {}, {}, {
|
||||
//Exits
|
||||
ENTRANCE(RR_FIRE_TEMPLE_MQ_LOWER_LIZALFOS_MAZE, true),
|
||||
//this cage is much more lenient than the lower cage as the switch is close to the front. sling, rang and bow all hit the switch easily, though might be too unintuitive for default logic
|
||||
//This shouldn't come up in most cases anyway as most methods to get here need either a melee weapon or explosives
|
||||
ENTRANCE(RR_FIRE_TEMPLE_MQ_MAZE_BOX_CAGE, AnyAgeTime([]{return logic->CanJumpslash() || logic->HasExplosives();})),
|
||||
ENTRANCE(RR_FIRE_TEMPLE_MQ_MAZE_BOX_CAGE, AnyAgeTime([]{return logic->CanJumpslash() || logic->HasExplosives() ||
|
||||
(ctx->GetTrickOption(RT_VISIBLE_COLLISION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG)));})),
|
||||
ENTRANCE(RR_FIRE_TEMPLE_MQ_SHORTCUT_CLIMB, logic->HasExplosives()),
|
||||
//Implies RR_FIRE_TEMPLE_MQ_LOWER_LIZALFOS_MAZE access
|
||||
ENTRANCE(RR_FIRE_TEMPLE_MQ_ABOVE_MAZE, logic->HasExplosives() && logic->CanUse(RG_MEGATON_HAMMER) && (logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SONG_OF_TIME)))),
|
||||
@@ -750,7 +749,7 @@ void RegionTable_Init_FireTemple() {
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_MQ_MAZE_BOX_CAGE] = Region("Fire Temple MQ Maze Box Cage", SCENE_FIRE_TEMPLE, {}, {
|
||||
//Locations
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)),
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST) && (ctx->GetTrickOption(RT_VISIBLE_COLLISION) || logic->CanBreakCrates())),
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_1, logic->CanBreakCrates()),
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_2, logic->CanBreakCrates()),
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_3, logic->CanBreakCrates()),
|
||||
|
||||
@@ -50,10 +50,9 @@ void RegionTable_Init_IceCavern() {
|
||||
}, {
|
||||
//Locations
|
||||
LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)),
|
||||
// very easy to break pot through ice with most weapons
|
||||
// Bow extesnion is possible, but very precise: X = 403, Z = 2062-3, Rot = -11475, needs a setup and is its own trick
|
||||
// Bow extension is possible, but very precise: X = 403, Z = 2062-3, Rot = -11475, needs a setup and is its own trick
|
||||
LOCATION(RC_ICE_CAVERN_FROZEN_POT_1, (logic->CanBreakPots() && logic->BlueFire()) || logic->HasExplosives() ||
|
||||
(ctx->GetTrickOption(RT_VISIBLE_COLLISION) && ((logic->CanStandingShield() && logic->CanUse(RG_KOKIRI_SWORD)) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER))) ||
|
||||
(ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanJumpslash()) ||
|
||||
(ctx->GetTrickOption(RT_ITEM_EXTENSION) && logic->CanUse(RG_HOOKSHOT))),
|
||||
LOCATION(RC_ICE_CAVERN_MAP_ROOM_LEFT_HEART, true),
|
||||
LOCATION(RC_ICE_CAVERN_MAP_ROOM_MIDDLE_HEART, true),
|
||||
|
||||
@@ -155,7 +155,7 @@ void RegionTable_Init_ShadowTemple() {
|
||||
LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_3, logic->CanUse(RG_BOOMERANG)),
|
||||
}, {
|
||||
//Exits
|
||||
ENTRANCE(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT, true),
|
||||
ENTRANCE(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT, !!ctx->GetTrickOption(RT_VISIBLE_COLLISION)),
|
||||
ENTRANCE(RR_SHADOW_TEMPLE_STONE_UMBRELLA_UPPER, ctx->GetTrickOption(RT_SHADOW_UMBRELLA_CLIP) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->TakeDamage()) || (logic->IsAdult && ((ctx->GetTrickOption(RT_SHADOW_UMBRELLA_HOVER) && logic->CanUse(RG_HOVER_BOOTS)) || logic->HasItem(RG_GORONS_BRACELET)))),
|
||||
});
|
||||
|
||||
@@ -638,7 +638,8 @@ void RegionTable_Init_ShadowTemple() {
|
||||
//Locations
|
||||
LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO) && logic->HasItem(RG_OPEN_CHEST)),
|
||||
LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)),
|
||||
LOCATION(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, logic->HasExplosives()),
|
||||
//The various methods for this can be a bit specific, might be worthy of it's own trick when it becomes relevant with dungeon shortcut settings.
|
||||
LOCATION(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, logic->HasExplosives() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA))),
|
||||
LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_BOAT_POT_1, logic->CanBreakPots()),
|
||||
LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_BOAT_POT_2, logic->CanBreakPots()),
|
||||
}, {
|
||||
|
||||
@@ -1358,7 +1358,7 @@ void RegionTable_Init_WaterTemple() {
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_MQ_CRATE_VORTEX_CAGE] = Region("Water Temple MQ Crate Vortex Cage", SCENE_WATER_TEMPLE, {}, {
|
||||
//Locations
|
||||
LOCATION(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) && logic->CanBreakCrates()),
|
||||
LOCATION(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) && (logic->CanBreakCrates() || ctx->GetTrickOption(RT_VISIBLE_COLLISION))),
|
||||
LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_BEHIND_GATE_CRATE_1, logic->CanBreakCrates()),
|
||||
LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_BEHIND_GATE_CRATE_2, logic->CanBreakCrates()),
|
||||
LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_BEHIND_GATE_CRATE_3, logic->CanBreakCrates()),
|
||||
|
||||
@@ -200,9 +200,10 @@ void RegionTable_Init_GerudoFortress() {
|
||||
LOCATION(RC_GF_ABOVE_JAIL_CRATE, true),
|
||||
}, {
|
||||
//Exits
|
||||
//you don't take fall damage if you land on the rock with the flag on for some reason
|
||||
//there's a trick to reach RR_GF_LONG_ROOF
|
||||
ENTRANCE(RR_GF_OUTSKIRTS, ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->TakeDamage()),
|
||||
//For some reason, you take fall damage if you backflip onto the fortress but not onto the sand
|
||||
//It's unintuitive to avoid being caught on landing, but that sends you to the same place anyway...
|
||||
ENTRANCE(RR_GF_OUTSKIRTS, true),
|
||||
ENTRANCE(RR_GF_NEAR_CHEST, logic->CanUse(RG_LONGSHOT)),
|
||||
ENTRANCE(RR_GF_BELOW_CHEST, logic->TakeDamage()),
|
||||
ENTRANCE(RR_GF_JAIL_WINDOW, logic->CanUse(RG_HOOKSHOT)),
|
||||
|
||||
@@ -243,7 +243,8 @@ void RegionTable_Init_Kakariko() {
|
||||
}, {
|
||||
//Locations
|
||||
LOCATION(RC_KAK_TRADE_ODD_MUSHROOM, logic->IsAdult && logic->CanUse(RG_ODD_MUSHROOM)),
|
||||
LOCATION(RC_KAK_GRANNYS_SHOP, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->CanUse(RG_ODD_MUSHROOM) || logic->TradeQuestStep(RG_ODD_MUSHROOM))),
|
||||
LOCATION(RC_KAK_GRANNYS_SHOP, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) &&
|
||||
(logic->CanUse(RG_ODD_MUSHROOM) || logic->TradeQuestStep(RG_ODD_MUSHROOM)) && GetCheckPrice() <= GetWalletCapacity()),
|
||||
}, {
|
||||
// Exits
|
||||
ENTRANCE(RR_KAK_BACKYARD, true),
|
||||
|
||||
@@ -537,11 +537,24 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
|
||||
: 500;
|
||||
result.currentAmmo = gSaveContext.rupees;
|
||||
break;
|
||||
case ITEM_BOMBCHU:
|
||||
result.currentCapacity = INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU ? 50 : 0;
|
||||
case ITEM_BOMBCHU: {
|
||||
auto bombchuBag = RAND_GET_OPTION(RSK_BOMBCHU_BAG);
|
||||
|
||||
uint8_t capacity = 0;
|
||||
|
||||
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU) {
|
||||
if (bombchuBag.Is(RO_BOMBCHU_BAG_PROGRESSIVE)) {
|
||||
capacity = OTRGlobals::Instance->gRandoContext->GetBombchuCapacity();
|
||||
} else {
|
||||
capacity = 50;
|
||||
}
|
||||
}
|
||||
|
||||
result.currentCapacity = capacity;
|
||||
result.maxCapacity = 50;
|
||||
result.currentAmmo = AMMO(ITEM_BOMBCHU);
|
||||
break;
|
||||
}
|
||||
case ITEM_BEAN:
|
||||
result.currentCapacity = INV_CONTENT(ITEM_BEAN) == ITEM_BEAN ? 10 : 0;
|
||||
result.maxCapacity = 10;
|
||||
@@ -702,7 +715,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) {
|
||||
bool shouldDisplayAmmo = trackerNumberDisplayMode == ITEM_TRACKER_NUMBER_AMMO ||
|
||||
trackerNumberDisplayMode == ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY ||
|
||||
// These items have a static capacity, so display ammo instead
|
||||
item.id == ITEM_BOMBCHU || item.id == ITEM_BEAN || item.id == QUEST_SKULL_TOKEN ||
|
||||
item.id == ITEM_BEAN || item.id == QUEST_SKULL_TOKEN ||
|
||||
item.id == ITEM_HEART_CONTAINER || item.id == ITEM_HEART_PIECE;
|
||||
|
||||
bool shouldDisplayMax = !(trackerNumberDisplayMode == ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY ||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ResourceManagerHelpers.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/Enhancements/randomizer/item_category_adj.h"
|
||||
|
||||
#define FLAGS 0
|
||||
|
||||
@@ -580,21 +581,7 @@ void EnBox_UpdateTexture(EnBox* this, PlayState* play) {
|
||||
this->dyna.actor.room != 6); // Exclude treasure game chests except for the final room
|
||||
|
||||
if (!isVanilla) {
|
||||
getItemCategory = chestItem.getItemCategory;
|
||||
// If they have bombchus, don't consider the bombchu item major
|
||||
if ((INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU &&
|
||||
((chestItem.modIndex == MOD_RANDOMIZER && chestItem.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) ||
|
||||
(chestItem.modIndex == MOD_NONE &&
|
||||
(chestItem.getItemId == GI_BOMBCHUS_5 || chestItem.getItemId == GI_BOMBCHUS_10 ||
|
||||
chestItem.getItemId == GI_BOMBCHUS_20)))) ||
|
||||
// If it's a bottle and they already have one, consider the item lesser
|
||||
((chestItem.modIndex == MOD_RANDOMIZER && chestItem.getItemId >= RG_BOTTLE_WITH_RED_POTION &&
|
||||
chestItem.getItemId <= RG_BOTTLE_WITH_POE) ||
|
||||
(chestItem.modIndex == MOD_NONE &&
|
||||
(chestItem.getItemId == GI_BOTTLE || chestItem.getItemId == GI_MILK_BOTTLE)) &&
|
||||
gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE)) {
|
||||
getItemCategory = ITEM_CATEGORY_LESSER;
|
||||
}
|
||||
getItemCategory = Randomizer_AdjustItemCategory(chestItem);
|
||||
}
|
||||
|
||||
switch (this->type) {
|
||||
|
||||
@@ -150,7 +150,9 @@ void EnMs_Talk(EnMs* this, PlayState* play) {
|
||||
|
||||
void EnMs_Sell(EnMs* this, PlayState* play) {
|
||||
if (Actor_HasParent(&this->actor, play)) {
|
||||
Rupees_ChangeBy(-sPrices[BEANS_BOUGHT]);
|
||||
if (GameInteractor_Should(VB_MAGIC_BEAN_SALESMAN_TAKE_MONEY, true, this)) {
|
||||
Rupees_ChangeBy(-sPrices[BEANS_BOUGHT]);
|
||||
}
|
||||
this->actor.parent = NULL;
|
||||
this->actionFunc = EnMs_TalkAfterPurchase;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user