From c18203878b4bc236902afe0e97e3a81aa17d8877 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Wed, 3 Aug 2022 00:14:38 -0500 Subject: [PATCH] Add shuffleCows options for randomizer --- .../randomizer/3drando/settings.cpp | 1 + .../Enhancements/randomizer/randomizer.cpp | 34 ++++++++++ .../Enhancements/randomizer/randomizerTypes.h | 1 + soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c | 68 ++++++++++++++++++- 4 files changed, 101 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 6bf2070697..9c110cd1fc 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2500,6 +2500,7 @@ namespace Settings { ShuffleRewards.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS]); ShuffleSongs.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_SONGS]); Tokensanity.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_TOKENS]); + ShuffleCows.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_COWS]); ShuffleKokiriSword.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD]); ShuffleOcarinas.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OCARINA]); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 3a6b23bb77..a11d4d4770 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2968,10 +2968,25 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_KF_MIDOS_BOTTOM_RIGHT_CHEST; } break; + case 52: + switch (actorParams) { + case -161: + return RC_KF_LINKS_HOUSE_COW; + } + break; + case 54: + switch (actorParams) { + case -376: + return RC_LLR_STABLES_LEFT_COW; + case -138: + return RC_LLR_STABLES_RIGHT_COW; + } case 55: switch (actorParams) { case 262: return RC_KAK_IMPAS_HOUSE_FREESTANDING_POH; + case -115: + return RC_KAK_IMPAS_HOUSE_COW; } break; case 56: @@ -3008,6 +3023,10 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_HF_DEKU_SCRUB_GROTTO; case 10: return RC_LW_DEKU_SCRUB_GROTTO_FRONT; + case 1973: + return RC_DMT_COW_GROTTO_COW; + case 3194: + return RC_HF_COW_GROTTO_COW; case 22988: return RC_KF_STORMS_GROTTO_CHEST; case -22988: @@ -3094,6 +3113,10 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act break; case 76: switch (actorParams) { + case -72: + return RC_LLR_TOWER_LEFT_COW; + case -282: + return RC_LLR_TOWER_RIGHT_COW; case 262: return RC_LLR_FREESTANDING_POH; } @@ -3252,6 +3275,8 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act break; case 90: switch (actorParams) { + case -421: + return RC_GV_COW; case 23200: return RC_GV_CHEST; case 262: @@ -3438,6 +3463,7 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0); cvarSettings[RSK_SHUFFLE_SONGS] = CVar_GetS32("gRandomizeShuffleSongs", 0); cvarSettings[RSK_SHUFFLE_TOKENS] = CVar_GetS32("gRandomizeShuffleTokens", 0); + cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0); cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0); // if we skip child zelda, we start with zelda's letter, and malon starts @@ -3956,6 +3982,14 @@ void DrawRandoEditor(bool& open) { "expected to be collected after getting Sun's Song."); PaddedSeparator(); + // Shuffle Cows + ImGui::Text(Settings::ShuffleCows.GetName().c_str()); + InsertHelpHoverText( + "Enabling this will let cows give you items upon performing Epona's Song in " + "front of them. There are 9 cows."); + SohImGui::EnhancementCombobox("gRandomizeShuffleCows", randoShuffleCows, 2, 0); + PaddedSeparator(); + if(CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) { // Shuffle Kokiri Sword SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), "gRandomizeShuffleKokiriSword"); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 04e6477832..f095ac068b 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -975,6 +975,7 @@ typedef enum { RSK_SHUFFLE_DUNGEON_REWARDS, RSK_SHUFFLE_SONGS, RSK_SHUFFLE_TOKENS, + RSK_SHUFFLE_COWS, RSK_SHUFFLE_WEIRD_EGG, RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, RSK_ITEM_POOL, diff --git a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c index 90ff14c31a..1f3a8a0e28 100644 --- a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c +++ b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c @@ -18,6 +18,11 @@ void func_809E0070(Actor* thisx, GlobalContext* globalCtx); void func_809DF494(EnCow* this, GlobalContext* globalCtx); void func_809DF6BC(EnCow* this, GlobalContext* globalCtx); +bool EnCow_IsSecondCowInTower(EnCow* this, GlobalContext* globalCtx); +bool EnCow_IsSecondCowInStable(EnCow* this, GlobalContext* globalCtx); +bool EnCow_IsSecondCowInGrotto(EnCow* this, GlobalContext* globalCtx); +bool EnCow_IsSecondCow(EnCow* this, GlobalContext* globalCtx); +GetItemID EnCow_GetItemFromCow(EnCow* this, GlobalContext* globalCtx, bool setFlag); void func_809DF778(EnCow* this, GlobalContext* globalCtx); void func_809DF7D8(EnCow* this, GlobalContext* globalCtx); void func_809DF870(EnCow* this, GlobalContext* globalCtx); @@ -106,6 +111,18 @@ void EnCow_Init(Actor* thisx, GlobalContext* globalCtx) { EnCow* this = (EnCow*)thisx; s32 pad; + // Move left cow in lon lon tower + if (EnCow_IsSecondCowInTower(thisx, globalCtx)) { + this->actor.world.pos.x = -229.0f; + this->actor.world.pos.z = 157.0f; + this->actor.shape.rot.y = 15783.0f; + } + + // Move right cow in lon lon stable + if (EnCow_IsSecondCowInStable(thisx, globalCtx)) { + this->actor.world.pos.x += 119.0f; + } + ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 72.0f); switch (this->actor.params) { case 0: @@ -209,12 +226,57 @@ void func_809DF730(EnCow* this, GlobalContext* globalCtx) { } } +bool EnCow_IsSecondCowInTower(EnCow* this, GlobalContext* globalCtx) { + return + gSaveContext.n64ddFlag && + globalCtx->sceneNum == SCENE_SOUKO && + (this->actor.world.pos.x + this->actor.world.pos.z == -173 || this->actor.world.pos.x + this->actor.world.pos.z == -72); +} + +bool EnCow_IsSecondCowInStable(EnCow* this, GlobalContext* globalCtx) { + return + gSaveContext.n64ddFlag && + globalCtx->sceneNum == SCENE_MALON_STABLE && + (this->actor.world.pos.x + this->actor.world.pos.z == -257 || this->actor.world.pos.x + this->actor.world.pos.z == -138); +} + +bool EnCow_IsSecondCowInGrotto(EnCow* this, GlobalContext* globalCtx) { + return gSaveContext.n64ddFlag && globalCtx->sceneNum == SCENE_KAKUSIANA && this->actor.world.pos.x + this->actor.world.pos.z == 3194; +} + +bool EnCow_IsSecondCow(EnCow* this, GlobalContext* globalCtx) { + return EnCow_IsSecondCowInTower(this, globalCtx) || EnCow_IsSecondCowInStable(this, globalCtx) || EnCow_IsSecondCowInGrotto(this, globalCtx); +} + +GetItemID EnCow_GetItemFromCow(EnCow* this, GlobalContext* globalCtx, bool setFlag) { + GetItemID itemId = ITEM_NONE; + + if (Inventory_HasEmptyBottle()) { + return GI_MILK; + } + + s32 collectableFlag = 0x1A; + if (EnCow_IsSecondCow(this, globalCtx)) { + collectableFlag = 0x19; + } + + if (gSaveContext.n64ddFlag && !Flags_GetCollectible(globalCtx, collectableFlag)) { + itemId = Randomizer_GetRandomizedItemId(GI_MILK, this->actor.id, this->actor.world.pos.x + this->actor.world.pos.z, globalCtx->sceneNum); + } + + if (setFlag) { + Flags_SetCollectible(globalCtx, collectableFlag); + } + + return itemId; +} + void func_809DF778(EnCow* this, GlobalContext* globalCtx) { if (Actor_HasParent(&this->actor, globalCtx)) { this->actor.parent = NULL; this->actionFunc = func_809DF730; } else { - func_8002F434(&this->actor, globalCtx, GI_MILK, 10000.0f, 100.0f); + func_8002F434(&this->actor, globalCtx, EnCow_GetItemFromCow(this, globalCtx, true), 10000.0f, 100.0f); } } @@ -223,13 +285,13 @@ void func_809DF7D8(EnCow* this, GlobalContext* globalCtx) { this->actor.flags &= ~ACTOR_FLAG_16; Message_CloseTextbox(globalCtx); this->actionFunc = func_809DF778; - func_8002F434(&this->actor, globalCtx, GI_MILK, 10000.0f, 100.0f); + func_8002F434(&this->actor, globalCtx, EnCow_GetItemFromCow(this, globalCtx, true), 10000.0f, 100.0f); } } void func_809DF870(EnCow* this, GlobalContext* globalCtx) { if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(globalCtx)) { - if (Inventory_HasEmptyBottle()) { + if (EnCow_GetItemFromCow(this, globalCtx, false) != ITEM_NONE) { Message_ContinueTextbox(globalCtx, 0x2007); this->actionFunc = func_809DF7D8; } else {