Skip to content

Commit

Permalink
Enhancement: Catch Poes with bottles
Browse files Browse the repository at this point in the history
  • Loading branch information
lilDavid committed Nov 25, 2023
1 parent 0ddb071 commit e341e6b
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 19 deletions.
1 change: 1 addition & 0 deletions soh/soh/Enhancements/presets.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const std::vector<const char*> enhancementsCvars = {
"gFasterHeavyBlockLift",
"gNoForcedNavi",
"gSkulltulaFreeze",
"gMMPoeBottling",
"gMMBunnyHood",
"gAdultBunnyHood",
"gFastChests",
Expand Down
28 changes: 15 additions & 13 deletions soh/soh/SohMenuBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ void DrawSettingsMenu() {
UIWidgets::Tooltip("Changes the scaling of the ImGui menu elements.");

UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);

static std::unordered_map<LUS::WindowBackend, const char*> windowBackendNames = {
{ LUS::WindowBackend::DX11, "DirectX" },
{ LUS::WindowBackend::SDL_OPENGL, "OpenGL"},
Expand Down Expand Up @@ -468,17 +468,17 @@ void DrawSettingsMenu() {
}
ImGui::EndMenu();
}

UIWidgets::Spacer(0);

if (ImGui::BeginMenu("Accessibility")) {
#if defined(_WIN32) || defined(__APPLE__)
UIWidgets::PaddedEnhancementCheckbox("Text to Speech", "gA11yTTS");
UIWidgets::Tooltip("Enables text to speech for in game dialog");
#endif
UIWidgets::PaddedEnhancementCheckbox("Disable Idle Camera Re-Centering", "gA11yDisableIdleCam");
UIWidgets::Tooltip("Disables the automatic re-centering of the camera when idle.");

ImGui::EndMenu();
}
ImGui::EndMenu();
Expand Down Expand Up @@ -602,6 +602,8 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("Allows the bunny hood to be equipped normally from the pause menu as adult.");
UIWidgets::PaddedEnhancementCheckbox("Mask Select in Inventory", "gMaskSelect", true, false);
UIWidgets::Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks");
UIWidgets::PaddedEnhancementCheckbox("Catch Poes with a bottle", "gMMPoeBottling", true, false);
UIWidgets::Tooltip("Catch Poes by swinging an empty bottle at them instead of from a text box like you can in Majora's Mask.");
UIWidgets::PaddedEnhancementCheckbox("Nuts explode bombs", "gNutsExplodeBombs", true, false);
UIWidgets::Tooltip("Makes nuts explode bombs, similar to how they interact with bombchus. This does not affect bombflowers.");
UIWidgets::PaddedEnhancementCheckbox("Equip Multiple Arrows at Once", "gSeparateArrows", true, false);
Expand Down Expand Up @@ -876,7 +878,7 @@ void DrawEnhancementsMenu() {
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BLUE_FIRE_ARROWS);
static const char* forceEnableBlueFireArrowsText =
"This setting is forcefully enabled because a savefile\nwith \"Blue Fire Arrows\" is loaded.";
UIWidgets::PaddedEnhancementCheckbox("Blue Fire Arrows", "gBlueFireArrows", true, false,
UIWidgets::PaddedEnhancementCheckbox("Blue Fire Arrows", "gBlueFireArrows", true, false,
forceEnableBlueFireArrows, forceEnableBlueFireArrowsText, UIWidgets::CheckboxGraphics::Checkmark);
UIWidgets::Tooltip("Allows Ice Arrows to melt red ice.\nMay require a room reload if toggled during gameplay.");

Expand All @@ -885,7 +887,7 @@ void DrawEnhancementsMenu() {
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SUNLIGHT_ARROWS);
static const char* forceEnableSunLightArrowsText =
"This setting is forcefully enabled because a savefile\nwith \"Sunlight Arrows\" is loaded.";
UIWidgets::PaddedEnhancementCheckbox("Sunlight Arrows", "gSunlightArrows", true, false,
UIWidgets::PaddedEnhancementCheckbox("Sunlight Arrows", "gSunlightArrows", true, false,
forceEnableSunLightArrows, forceEnableSunLightArrowsText, UIWidgets::CheckboxGraphics::Checkmark);
UIWidgets::Tooltip("Allows Light Arrows to activate sun switches.\nMay require a room reload if toggled during gameplay.");

Expand Down Expand Up @@ -1059,8 +1061,8 @@ void DrawEnhancementsMenu() {
"Fixes an incorrect calculation that acted like water underneath ground was above it.");
UIWidgets::PaddedEnhancementCheckbox("Fix Bush Item Drops", "gBushDropFix", true, false);
UIWidgets::Tooltip("Fixes the bushes to drop items correctly rather than spawning undefined items.");
UIWidgets::PaddedEnhancementCheckbox("Fix falling from vine edges", "gFixVineFall", true, false);
UIWidgets::Tooltip("Prevents immediately falling off climbable surfaces if climbing on the edges.");
UIWidgets::PaddedEnhancementCheckbox("Fix falling from vine edges", "gFixVineFall", true, false);
UIWidgets::Tooltip("Prevents immediately falling off climbable surfaces if climbing on the edges.");
UIWidgets::PaddedEnhancementCheckbox("Fix Link's eyes open while sleeping", "gFixEyesOpenWhileSleeping", true, false);
UIWidgets::Tooltip("Fixes Link's eyes being open in the opening cutscene when he is supposed to be sleeping.");

Expand Down Expand Up @@ -1386,12 +1388,12 @@ void DrawCheatsMenu() {
if (ImGui::Button("Change Age")) {
CVarSetInteger("gSwitchAge", 1);
}
UIWidgets::Tooltip("Switches Link's age and reloads the area.");
UIWidgets::Tooltip("Switches Link's age and reloads the area.");

if (ImGui::Button("Clear Cutscene Pointer")) {
GameInteractor::RawAction::ClearCutscenePointer();
}
UIWidgets::Tooltip("Clears the cutscene pointer to a value safe for wrong warps.");
UIWidgets::Tooltip("Clears the cutscene pointer to a value safe for wrong warps.");

ImGui::EndMenu();
}
Expand Down Expand Up @@ -1565,12 +1567,12 @@ void DrawRandomizerMenu() {
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE ||
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_VANILLA &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_OWN_DUNGEON &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_STARTWITH) ||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_STARTWITH) ||
!IS_RANDO) {
disableKeyColors = false;
}

static const char* disableKeyColorsText =
static const char* disableKeyColorsText =
"This setting is disabled because a savefile is loaded without any key\n"
"shuffle settings set to \"Any Dungeon\", \"Overworld\" or \"Anywhere\"";

Expand Down Expand Up @@ -1626,4 +1628,4 @@ void SohMenuBar::DrawElement() {
ImGui::EndMenuBar();
}
}
} // namespace SohGui
} // namespace SohGui
12 changes: 10 additions & 2 deletions soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ void func_80AD58D4(EnPoField* this, PlayState* play) {
if (this->actionTimer != 0) {
this->actionTimer--;
}
if (Actor_ProcessTalkRequest(&this->actor, play)) {
if (!CVarGetInteger("gMMPoeBottling", 0) && Actor_ProcessTalkRequest(&this->actor, play)) {
EnPoField_SetupInteractWithSoul(this);
return;
}
Expand All @@ -668,7 +668,15 @@ void func_80AD58D4(EnPoField* this, PlayState* play) {
EnPoField_SetupSoulDisappear(this);
return;
}
if (this->collider.base.ocFlags1 & OC1_HIT) {
if (CVarGetInteger("gMMPoeBottling", 0)) {
// do not collide
if (Actor_HasParent(&this->actor, play)) {
Actor_Kill(&this->actor);
}

// GI_MAX in this case allows the player to catch the actor in a bottle
func_8002F434(&this->actor, play, GI_MAX, 35.0f, 60.0f);
} else if (this->collider.base.ocFlags1 & OC1_HIT) {
this->actor.flags |= ACTOR_FLAG_WILL_TALK;
func_8002F2F4(&this->actor, play);
} else {
Expand Down
13 changes: 11 additions & 2 deletions soh/src/overlays/actors/ovl_En_Poh/z_en_poh.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,8 @@ void func_80ADFE80(EnPoh* this, PlayState* play) {
if (this->unk_198 != 0) {
this->unk_198--;
}
if (Actor_ProcessTalkRequest(&this->actor, play)) {
if (!(CVarGetInteger("gMMPoeBottling", 0) && this->actor.params < EN_POH_SHARP) &&
Actor_ProcessTalkRequest(&this->actor, play)) {
if (this->actor.params >= EN_POH_SHARP) {
func_80ADE9BC(this);
} else {
Expand All @@ -783,7 +784,15 @@ void func_80ADFE80(EnPoh* this, PlayState* play) {
this->actor.flags &= ~ACTOR_FLAG_WILL_TALK;
return;
}
if (this->colliderCyl.base.ocFlags1 & OC1_HIT) {
if (CVarGetInteger("gMMPoeBottling", 0) && this->actor.params < EN_POH_SHARP) {
if (Actor_HasParent(&this->actor, play)) {
Actor_Kill(&this->actor);
return;
}

// GI_MAX in this case allows the player to catch the actor in a bottle
func_8002F434(&this->actor, play, GI_MAX, 35.0f, 60.0f);
} else if (this->colliderCyl.base.ocFlags1 & OC1_HIT) {
this->actor.flags |= ACTOR_FLAG_WILL_TALK;
func_8002F2F4(&this->actor, play);
} else {
Expand Down
22 changes: 20 additions & 2 deletions soh/src/overlays/actors/ovl_player_actor/z_player.c
Original file line number Diff line number Diff line change
Expand Up @@ -13239,6 +13239,8 @@ static BottleCatchInfo D_80854A04[] = {
{ ACTOR_EN_FISH, ITEM_FISH, 0x1F, 0x47 },
{ ACTOR_EN_ICE_HONO, ITEM_BLUE_FIRE, 0x20, 0x5D },
{ ACTOR_EN_INSECT, ITEM_BUG, 0x21, 0x7A },
{ ACTOR_EN_POH, ITEM_POE, PLAYER_IA_BOTTLE_POE, 0x97 },
{ ACTOR_EN_PO_FIELD, ITEM_BIG_POE, PLAYER_IA_BOTTLE_BIG_POE, 0xF9 },
};

void func_8084ECA4(Player* this, PlayState* play) {
Expand Down Expand Up @@ -13281,13 +13283,29 @@ void func_8084ECA4(Player* this, PlayState* play) {

if (this->interactRangeActor != NULL) {
catchInfo = &D_80854A04[0];
for (i = 0; i < 4; i++, catchInfo++) {
for (i = 0; i < ARRAY_COUNT(D_80854A04); i++, catchInfo++) {
if (this->interactRangeActor->id == catchInfo->actorId) {
break;
}
}

if (i < 4) {
if (catchInfo->actorId == ACTOR_EN_POH || catchInfo->actorId == ACTOR_EN_PO_FIELD) {
// Don't catch Sharp or Flat
// I think they talk to you before you can get in catching range, but might as well prevent it outright
if (catchInfo->actorId == ACTOR_EN_POH && this->interactRangeActor->params >= 2) {
i = ARRAY_COUNT(D_80854A04);
}
// If the catch is a small field Poe (as opposed to a Big Poe), catch a graveyard Poe instead
if (catchInfo->actorId == ACTOR_EN_PO_FIELD && this->interactRangeActor->params == 0) {
i--;
catchInfo--;
}
if (!CVarGetInteger("gMMPoeBottling", 0)) {
i = ARRAY_COUNT(D_80854A04);
}
}

if (i < ARRAY_COUNT(D_80854A04)) {
this->unk_84F = i + 1;
this->unk_850 = 0;
this->interactRangeActor->parent = &this->actor;
Expand Down

0 comments on commit e341e6b

Please sign in to comment.