diff --git a/soh/include/z64player.h b/soh/include/z64player.h index 0425c8eae..6e98b2846 100644 --- a/soh/include/z64player.h +++ b/soh/include/z64player.h @@ -374,6 +374,7 @@ typedef enum { FLAG_SCENE_TREASURE, FLAG_SCENE_CLEAR, FLAG_SCENE_COLLECTIBLE, + FLAG_COW_MILKED } FlagType; typedef struct { 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 36b5d2032..4921acb7d 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,7 +18,7 @@ void func_809E0070(Actor* thisx, GlobalContext* globalCtx); void func_809DF494(EnCow* this, GlobalContext* globalCtx); void func_809DF6BC(EnCow* this, GlobalContext* globalCtx); -struct CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx); +CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx); void EnCow_MoveForRandomizer(EnCow* this, GlobalContext* globalCtx); GetItemID EnCow_GetRandomizerItem(EnCow* this, GlobalContext* globalCtx); void func_809DF778(EnCow* this, GlobalContext* globalCtx); @@ -216,12 +216,7 @@ void func_809DF730(EnCow* this, GlobalContext* globalCtx) { } } -struct CowInfo { - int cowId; - RandomizerCheck randomizerCheck; -}; - -struct CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx) { +CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx) { struct CowInfo cowInfo; cowInfo.cowId = -1; @@ -294,13 +289,16 @@ void EnCow_MoveForRandomizer(EnCow* this, GlobalContext* globalCtx) { } void EnCow_SetCowMilked(EnCow* this, GlobalContext* globalCtx) { - struct CowInfo cowInfo = EnCow_GetInfo(this, globalCtx); - gSaveContext.cowsMilked[cowInfo.cowId] = 1; + CowInfo cowInfo = EnCow_GetInfo(this, globalCtx); + Player* player = GET_PLAYER(globalCtx); + player->pendingFlag.flagID = cowInfo.cowId; + player->pendingFlag.flagType = FLAG_COW_MILKED; + // gSaveContext.cowsMilked[cowInfo.cowId] = 1; } GetItemID EnCow_GetRandomizerItem(EnCow* this, GlobalContext* globalCtx) { GetItemID itemId = ITEM_NONE; - struct CowInfo cowInfo = EnCow_GetInfo(this, globalCtx); + CowInfo cowInfo = EnCow_GetInfo(this, globalCtx); if (!gSaveContext.cowsMilked[cowInfo.cowId]) { itemId = Randomizer_GetItemIdFromKnownCheck(cowInfo.randomizerCheck, GI_MILK); @@ -318,7 +316,8 @@ void func_809DF778(EnCow* this, GlobalContext* globalCtx) { } else { if (gSaveContext.n64ddFlag) { GetItemID itemId = EnCow_GetRandomizerItem(this, globalCtx); - func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 100.0f); + // func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 100.0f); + Item_Give(globalCtx, itemId); EnCow_SetCowMilked(this, globalCtx); if (itemId == GI_ICE_TRAP) { Message_StartTextbox(globalCtx, 0xF8, &this->actor); @@ -367,6 +366,24 @@ void func_809DF8FC(EnCow* this, GlobalContext* globalCtx) { func_809DF494(this, globalCtx); } +bool EnCow_HasBeenMilked(EnCow* this, GlobalContext* globalCtx) { + CowInfo cowInfo = EnCow_GetInfo(this, globalCtx); + return gSaveContext.cowsMilked[cowInfo.cowId]; +} + +void EnCow_GivePlayerRandomizedItem(EnCow* this, GlobalContext* globalCtx) { + if (!EnCow_HasBeenMilked(this, globalCtx)) { + CowInfo cowInfo = EnCow_GetInfo(this, globalCtx); + GetItemID itemId = Randomizer_GetItemIdFromKnownCheck(cowInfo.randomizerCheck, GI_MILK); + // GiveItemWithoutActor(globalCtx, itemId); + func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 100.0f); + } else { + // once we've gotten the rando reward from the cow, + // return them to the their default action function + this->actionFunc = func_809DF96C; + } +} + void func_809DF96C(EnCow* this, GlobalContext* globalCtx) { if ((globalCtx->msgCtx.ocarinaMode == OCARINA_MODE_00) || (globalCtx->msgCtx.ocarinaMode == OCARINA_MODE_04)) { if (DREG(53) != 0) { @@ -377,6 +394,17 @@ void func_809DF96C(EnCow* this, GlobalContext* globalCtx) { if ((this->actor.xzDistToPlayer < 150.0f) && (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x61A8)) { DREG(53) = 0; + // when randomized with cowsanity, if we haven't gotten the + // reward from this cow yet, give that, otherwise use the + // vanilla cow behavior + if (gSaveContext.n64ddFlag && + Randomizer_GetSettingValue(RSK_SHUFFLE_COWS) && + !EnCow_HasBeenMilked(this, globalCtx)) { + EnCow_SetCowMilked(this, globalCtx); + globalCtx->msgCtx.ocarinaMode = OCARINA_MODE_00; + this->actionFunc = EnCow_GivePlayerRandomizedItem; + return; + } this->actionFunc = func_809DF8FC; this->actor.flags |= ACTOR_FLAG_16; func_8002F2CC(&this->actor, globalCtx, 170.0f); diff --git a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h index ccb165bf7..a5c66f1da 100644 --- a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h +++ b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h @@ -21,4 +21,9 @@ typedef struct EnCow { /* 0x027C */ EnCowActionFunc actionFunc; } EnCow; // size = 0x0280 +typedef struct CowInfo { + int cowId; + RandomizerCheck randomizerCheck; +} CowInfo; + #endif diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 34a94c67b..c3df51636 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6245,6 +6245,9 @@ void Player_SetPendingFlag(Player* this, GlobalContext* globalCtx) { case FLAG_SCENE_TREASURE: Flags_SetTreasure(globalCtx, this->pendingFlag.flagID); break; + case FLAG_COW_MILKED: + gSaveContext.cowsMilked[this->pendingFlag.flagID] = 1; + break; case FLAG_NONE: default: break;