Bombchu logic fixes, Add BetterBombchShopping enhancment and some adjacent cleanups (#3733)

* Initial Bombchu rework implementation

* Finish bombchus in logic overhaul

* address reviews

* Post resolution fixes

* fix git being dumb

* Readd Child Wallet To Bombchu Bowling Logic

* post merge fixes

* fix some oversights in bombchu shopping logic

* doesn't work, linker errors

* cleanup old reviews

* Make it build, likely broken by VB

* attempt to fix carpet man second purchse text

* commit to change branch

* mostly have carpet guy working

* badly fix carpet salesman

* fix better bombchu shopping

* fix bombchu drops

* remember you need bombchus in inventory to get drops

* Address reviews

* post-SCL clean up and redo the bombchu ammo logic to apply better to the spirit edge case

* fix oversight which could have allowed for bombchus to logical exist when they shouldn't

* Remove special bombchu playthrough checks which are causing bugs and no longer needed

* fix Slingshot logic reset

* Convert helpers I touched into CanUse and HasItem

* last cleanups
This commit is contained in:
Pepper0ni
2024-08-18 00:10:11 +01:00
committed by GitHub
parent d3edbcd042
commit 9c2e773ce4
45 changed files with 521 additions and 414 deletions

View File

@@ -1454,6 +1454,7 @@ void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) {
CLOSE_DISPS(play->state.gfxCtx);
}
// #region [Randomizer] [Enchancment]
/**
* Sometimes convert the given drop ID into a bombchu.
* Returns the new drop type ID.
@@ -1483,6 +1484,7 @@ s16 EnItem00_ConvertBombDropToBombchu(s16 dropId) {
}
}
}
// #endregion
/**
* Converts a given drop type ID based on link's current age, health and owned items.
@@ -1501,11 +1503,14 @@ s16 func_8001F404(s16 dropId) {
}
}
if ((CVarGetInteger(CVAR_ENHANCEMENT("BombchuDrops"), 0) ||
// #region [Randomizer] [Enchancment]
if ((CVarGetInteger(CVAR_ENHANCEMENT("EnableBombchuDrops"), 0) ||
(IS_RANDO && Randomizer_GetSettingValue(RSK_ENABLE_BOMBCHU_DROPS) == 1)) &&
(dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_B || dropId == ITEM00_BOMBS_SPECIAL)) {
(dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_B || dropId == ITEM00_BOMBS_SPECIAL) &&
(!IS_RANDO || Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) || INV_CONTENT(ITEM_BOMB) != ITEM_NONE)) {
dropId = EnItem00_ConvertBombDropToBombchu(dropId);
}
// #endregion
// This is convoluted but it seems like it must be a single condition to match
// clang-format off

View File

@@ -1870,7 +1870,7 @@ void Randomizer_GameplayStats_SetTimestamp(uint16_t item) {
return;
}
// Count any bombchu pack as bombchus
if ((item >= RG_BOMBCHU_5 && item <= RG_BOMBCHU_DROP) || item == RG_PROGRESSIVE_BOMBCHUS) {
if ((item >= RG_BOMBCHU_5 && item <= RG_BOMBCHU_20) || item == RG_PROGRESSIVE_BOMBCHUS) {
if (gSaveContext.sohStats.itemTimestamp[ITEM_BOMBCHU] = 0) {
gSaveContext.sohStats.itemTimestamp[ITEM_BOMBCHU] = time;
}

View File

@@ -19,7 +19,7 @@ void EnGirlA_Update(Actor* thisx, PlayState* play);
void EnGirlA_SetItemOutOfStock(PlayState* play, EnGirlA* this);
void EnGirlA_UpdateStockedItem(PlayState* play, EnGirlA* this);
void EnGirlA_InitializeItemAction(EnGirlA* this, PlayState* play);
void EnGirlA_WaitForObject(EnGirlA* this, PlayState* play);
void EnGirlA_Update2(EnGirlA* this, PlayState* play);
void func_80A3C498(Actor* thisx, PlayState* play, s32 flags);
void EnGirlA_Draw(Actor* thisx, PlayState* play);
@@ -213,7 +213,7 @@ static ShopItemEntry shopItemEntries[] = {
/* SI_ZORA_TUNIC */
{ OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, NULL, 300, 1, 0x00AB, 0x0094, GI_TUNIC_ZORA, EnGirlA_CanBuy_ZoraTunic,
EnGirlA_ItemGive_ZoraTunic, EnGirlA_BuyEvent_ZoraTunic },
/* SI_HEART */
/* SI_RECOVERY_HEART */
{ OBJECT_GI_HEART, GID_HEART, NULL, 10, 16, 0x00AC, 0x0095, GI_HEART, EnGirlA_CanBuy_Health,
EnGirlA_ItemGive_Health, EnGirlA_BuyEvent_ShieldDiscount },
/* SI_MILK_BOTTLE */
@@ -327,78 +327,139 @@ void EnGirlA_SetupAction(EnGirlA* this, EnGirlAActionFunc func) {
this->actionFunc = func;
}
s32 EnGirlA_TryChangeShopItem(EnGirlA* this, PlayState* play) {
// #region SOH [Enhancement] [Randomizer]
s32 EnGirlA_TryChangeShopItemShip(EnGirlA* this, PlayState* play) {
if (!(IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0))){
switch (this->actor.params) {
case SI_BOMBCHU_10_2:
if (Flags_GetItemGetInf(ITEMGETINF_06)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_10_3:
if (Flags_GetItemGetInf(ITEMGETINF_07)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_20_3:
if (Flags_GetItemGetInf(ITEMGETINF_08)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_20_4:
if (Flags_GetItemGetInf(ITEMGETINF_09)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_10_4:
if (Flags_GetItemGetInf(ITEMGETINF_0A)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_10_1:
if (Flags_GetItemGetInf(ITEMGETINF_03)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_20_1:
if (Flags_GetItemGetInf(ITEMGETINF_04)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_20_2:
if (Flags_GetItemGetInf(ITEMGETINF_05)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
}
}
if (this->actor.params == SI_MILK_BOTTLE){
if (Flags_GetItemGetInf(ITEMGETINF_TALON_BOTTLE)) {
this->actor.params = SI_RECOVERY_HEART;
return true;
}
} else if (this->actor.params == SI_RANDOMIZED_ITEM) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex);
if (Flags_GetRandomizerInf(shopItemIdentity.randomizerInf)) {
this->actor.params = SI_SOLD_OUT;
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
// Undo the rotation for spiritual stones
if (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE) {
this->actor.shape.rot.y = this->actor.shape.rot.y - 20000;
}
return true;
}
}
return false;
}
// #endregion
s32 EnGirlA_TryChangeShopItem(EnGirlA* this) {
switch (this->actor.params) {
case SI_MILK_BOTTLE:
if (Flags_GetItemGetInf(ITEMGETINF_TALON_BOTTLE)) {
this->actor.params = SI_HEART;
if (GET_ITEMGETINF(ITEMGETINF_TALON_BOTTLE)) {
this->actor.params = SI_RECOVERY_HEART;
return true;
}
break;
case SI_BOMBCHU_10_2:
if (Flags_GetItemGetInf(ITEMGETINF_06)) {
if (GET_ITEMGETINF(ITEMGETINF_06)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_10_3:
if (Flags_GetItemGetInf(ITEMGETINF_07)) {
if (GET_ITEMGETINF(ITEMGETINF_07)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_20_3:
if (Flags_GetItemGetInf(ITEMGETINF_08)) {
if (GET_ITEMGETINF(ITEMGETINF_08)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_20_4:
if (Flags_GetItemGetInf(ITEMGETINF_09)) {
if (GET_ITEMGETINF(ITEMGETINF_09)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_10_4:
if (Flags_GetItemGetInf(ITEMGETINF_0A)) {
if (GET_ITEMGETINF(ITEMGETINF_0A)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_10_1:
if (Flags_GetItemGetInf(ITEMGETINF_03)) {
if (GET_ITEMGETINF(ITEMGETINF_03)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_20_1:
if (Flags_GetItemGetInf(ITEMGETINF_04)) {
if (GET_ITEMGETINF(ITEMGETINF_04)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_BOMBCHU_20_2:
if (Flags_GetItemGetInf(ITEMGETINF_05)) {
if (GET_ITEMGETINF(ITEMGETINF_05)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
case SI_RANDOMIZED_ITEM: {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex);
if (Flags_GetRandomizerInf(shopItemIdentity.randomizerInf)) {
this->actor.params = SI_SOLD_OUT;
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
// Undo the rotation for spiritual stones
if (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE) {
this->actor.shape.rot.y = this->actor.shape.rot.y - 20000;
}
return true;
}
break;
}
}
return false;
}
@@ -413,12 +474,12 @@ void EnGirlA_InitItem(EnGirlA* this, PlayState* play) {
osSyncPrintf("引数がおかしいよ(arg_data=%d)\n", this->actor.params);
osSyncPrintf(VT_RST);
assert((params >= SI_MAX) && (params < 0));
//ASSERT(0, "0", "../z_en_girlA.c", 1421); zret assert, currently errors due to missing macro
return;
}
if (!IS_RANDO || Randomizer_GetSettingValue(RSK_SHOPSANITY) == RO_SHOPSANITY_OFF) {
this->objBankIndex = Object_GetIndex(&play->objectCtx, shopItemEntries[params].objID);
} else {
// #region [Randomizer]
if (IS_RANDO && !Randomizer_GetSettingValue(RSK_SHOPSANITY) == RO_SHOPSANITY_OFF) {
s16 objectId = shopItemEntries[params].objID;
if (params == SI_RANDOMIZED_ITEM) {
@@ -428,33 +489,48 @@ void EnGirlA_InitItem(EnGirlA* this, PlayState* play) {
objectId = getItemEntry.objectId;
}
this->objBankIndex = Object_GetIndex(&play->objectCtx, objectId);
this->requiredObjectSlot = Object_GetIndex(&play->objectCtx, objectId);
// If the object isn't normally spawned by the shop scene, then spawn it now
if (this->objBankIndex < 0) {
this->objBankIndex = Object_Spawn(&play->objectCtx, objectId);
if (this->requiredObjectSlot < 0) {
this->requiredObjectSlot = Object_Spawn(&play->objectCtx, objectId);
}
}
// #endregion
else {
this->requiredObjectSlot = Object_GetIndex(&play->objectCtx, shopItemEntries[params].objID);
}
if (this->objBankIndex < 0) {
if (this->requiredObjectSlot < 0) {
Actor_Kill(&this->actor);
osSyncPrintf(VT_COL(RED, WHITE));
osSyncPrintf("バンクが無いよ!!(%s)\n", sShopItemDescriptions[params]);
osSyncPrintf(VT_RST);
assert(this->objBankIndex < 0);
//ASSERT(0, "0", "../z_en_girlA.c", 1434); zret assert, currently errors due to missing macro
return;
}
this->actor.params = params;
this->actionFunc2 = EnGirlA_InitializeItemAction;
this->actionFunc2 = EnGirlA_WaitForObject;
}
void EnGirlA_Init(Actor* thisx, PlayState* play) {
EnGirlA* this = (EnGirlA*)thisx;
// #region [Randomizer] [Enhancment]
if (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)){
EnGirlA* this = (EnGirlA*)thisx;
EnGirlA_TryChangeShopItem(this, play);
EnGirlA_InitItem(this, play);
osSyncPrintf("%s(%2d)初期設定\n", sShopItemDescriptions[this->actor.params], this->actor.params);
EnGirlA_TryChangeShopItemShip(this, play);
EnGirlA_InitItem(this, play);
osSyncPrintf("%s(%2d)初期設定\n", sShopItemDescriptions[this->actor.params], this->actor.params);
}
// #endregion
else {
EnGirlA* this = (EnGirlA*)thisx;
EnGirlA_TryChangeShopItem(this);
EnGirlA_InitItem(this, play);
osSyncPrintf("%s(%2d)初期設定\n", sShopItemDescriptions[this->actor.params], this->actor.params);
}
}
void EnGirlA_Destroy(Actor* thisx, PlayState* play) {
@@ -1035,10 +1111,12 @@ void EnGirlA_BuyEvent_ObtainBombchuPack(PlayState* play, EnGirlA* this) {
Rupees_ChangeBy(-this->basePrice);
// Normally, buying a bombchu pack sets a flag indicating the pack is now sold out
// If we're in rando, skip setting that flag so they can be purchased repeatedly
if (IS_RANDO) {
// If they're in logic for rando, skip setting that flag so they can be purchased repeatedly
// #region [Enhancment]
if (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) {
return;
}
// #endregion
switch (this->actor.params) {
case SI_BOMBCHU_10_2:
@@ -1153,21 +1231,35 @@ void EnGirlA_SetItemOutOfStock(PlayState* play, EnGirlA* this) {
}
void EnGirlA_UpdateStockedItem(PlayState* play, EnGirlA* this) {
ShopItemEntry* itemEntry;
// #region [Randomizer] [Enhancment]
if (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)){
ShopItemEntry* itemEntry;
if (EnGirlA_TryChangeShopItemShip(this, play)) {
EnGirlA_InitItem(this, play);
itemEntry = &shopItemEntries[this->actor.params];
if (EnGirlA_TryChangeShopItem(this, play)) {
EnGirlA_InitItem(this, play);
itemEntry = &shopItemEntries[this->actor.params];
if (this->actor.params == SI_RANDOMIZED_ITEM) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex);
this->actor.textId = 0x9100 + (shopItemIdentity.randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1);
if (this->actor.params == SI_RANDOMIZED_ITEM) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex);
this->actor.textId = 0x9100 + (shopItemIdentity.randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1);
} else {
this->actor.textId = itemEntry->itemDescTextId;
}
} else {
this->actor.textId = itemEntry->itemDescTextId;
this->isInvisible = false;
this->actor.draw = EnGirlA_Draw;
}
}
// #endregion
else {
ShopItemEntry* itemEntry;
if (EnGirlA_TryChangeShopItem(this)) {
EnGirlA_InitItem(this, play);
itemEntry = &shopItemEntries[this->actor.params];
this->actor.textId = itemEntry->itemDescTextId;
} else {
this->isInvisible = false;
this->actor.draw = EnGirlA_Draw;
}
} else {
this->isInvisible = false;
this->actor.draw = EnGirlA_Draw;
}
}
@@ -1186,13 +1278,13 @@ s32 EnGirlA_TrySetMaskItemDescription(EnGirlA* this, PlayState* play) {
return false;
}
void EnGirlA_InitializeItemAction(EnGirlA* this, PlayState* play) {
void EnGirlA_WaitForObject(EnGirlA* this, PlayState* play) {
s16 params = this->actor.params;
ShopItemEntry* itemEntry = &shopItemEntries[params];
if (Object_IsLoaded(&play->objectCtx, this->objBankIndex)) {
if (Object_IsLoaded(&play->objectCtx, this->requiredObjectSlot)) {
this->actor.flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED;
this->actor.objBankIndex = this->objBankIndex;
this->actor.objBankIndex = this->requiredObjectSlot;
switch (this->actor.params) {
case SI_KEATON_MASK:
if (Flags_GetItemGetInf(ITEMGETINF_38)) {
@@ -1255,49 +1347,78 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, PlayState* play) {
if (!EnGirlA_TrySetMaskItemDescription(this, play)) {
EnGirlA_SetItemDescription(play, this);
}
this->setOutOfStockFunc = EnGirlA_SetItemOutOfStock;
this->updateStockedItemFunc = EnGirlA_UpdateStockedItem;
this->getItemId = itemEntry->getItemId;
this->canBuyFunc = itemEntry->canBuyFunc;
this->itemGiveFunc = itemEntry->itemGiveFunc;
this->buyEventFunc = itemEntry->buyEventFunc;
// If chus are in logic, make the 10 pack affordable without a wallet upgrade
if (IS_RANDO && this->getItemId == GI_BOMBCHUS_10) {
this->basePrice = 99;
} else {
this->basePrice = itemEntry->price;
}
this->itemCount = itemEntry->count;
this->hiliteFunc = itemEntry->hiliteFunc;
this->giDrawId = itemEntry->giDrawId;
osSyncPrintf("%s(%2d)\n", sShopItemDescriptions[params], params);
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
Actor_SetScale(&this->actor, 0.25f);
this->actor.shape.yOffset = 24.0f;
this->actor.shape.shadowScale = 4.0f;
this->actor.floorHeight = this->actor.home.pos.y;
this->actor.gravity = 0.0f;
EnGirlA_SetupAction(this, EnGirlA_Noop);
this->isInitialized = true;
this->actionFunc2 = EnGirlA_Update2;
this->isSelected = false;
this->yRotation = 0;
this->yRotationInit = this->actor.shape.rot.y;
if (params == SI_RANDOMIZED_ITEM) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex);
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
this->actor.textId = 0x9100 + (shopItemIdentity.randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1);
this->itemBuyPromptTextId = 0x9100 + ((shopItemIdentity.randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS);
this->getItemId = getItemEntry.getItemId;
this->basePrice = shopItemIdentity.itemPrice;
this->giDrawId = getItemEntry.gid;
// Correct the rotation for spiritual stones, but only if mysterious shuffle isn't on, else it's obvious what's there in shops
if (!CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE)) {
this->actor.shape.rot.y = this->actor.shape.rot.y + 20000;
// #region [Enhancment] [Randomizer]
if (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) {
this->setOutOfStockFunc = EnGirlA_SetItemOutOfStock;
this->updateStockedItemFunc = EnGirlA_UpdateStockedItem;
this->getItemId = itemEntry->getItemId;
this->canBuyFunc = itemEntry->canBuyFunc;
this->itemGiveFunc = itemEntry->itemGiveFunc;
this->buyEventFunc = itemEntry->buyEventFunc;
// If Better Bombchu Shopping is on, make the 10 pack affordable without a wallet upgrade
if (this->getItemId == GI_BOMBCHUS_10) {
this->basePrice = 99;
}
else {
this->basePrice = itemEntry->price;
}
this->itemCount = itemEntry->count;
this->hiliteFunc = itemEntry->hiliteFunc;
this->giDrawId = itemEntry->giDrawId;
osSyncPrintf("%s(%2d)\n", sShopItemDescriptions[params], params);
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
Actor_SetScale(&this->actor, 0.25f);
this->actor.shape.yOffset = 24.0f;
this->actor.shape.shadowScale = 4.0f;
this->actor.floorHeight = this->actor.home.pos.y;
this->actor.gravity = 0.0f;
EnGirlA_SetupAction(this, EnGirlA_Noop);
this->isInitialized = true;
this->actionFunc2 = EnGirlA_Update2;
this->isSelected = false;
this->yRotation = 0;
this->yRotationInit = this->actor.shape.rot.y;
if (params == SI_RANDOMIZED_ITEM) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex);
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
this->actor.textId = 0x9100 + (shopItemIdentity.randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1);
this->itemBuyPromptTextId = 0x9100 + ((shopItemIdentity.randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS);
this->getItemId = getItemEntry.getItemId;
this->basePrice = shopItemIdentity.itemPrice;
this->giDrawId = getItemEntry.gid;
// Correct the rotation for spiritual stones, but only if mysterious shuffle isn't on, else it's obvious what's there in shops
if (!CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE)) {
this->actor.shape.rot.y = this->actor.shape.rot.y + 20000;
}
}
}
// #endregion
else {
this->setOutOfStockFunc = EnGirlA_SetItemOutOfStock;
this->updateStockedItemFunc = EnGirlA_UpdateStockedItem;
this->getItemId = itemEntry->getItemId;
this->canBuyFunc = itemEntry->canBuyFunc;
this->itemGiveFunc = itemEntry->itemGiveFunc;
this->buyEventFunc = itemEntry->buyEventFunc;
this->basePrice = itemEntry->price;
this->itemCount = itemEntry->count;
this->hiliteFunc = itemEntry->hiliteFunc;
this->giDrawId = itemEntry->giDrawId;
osSyncPrintf("%s(%2d)\n", sShopItemDescriptions[params], params);
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
Actor_SetScale(&this->actor, 0.25f);
this->actor.shape.yOffset = 24.0f;
this->actor.shape.shadowScale = 4.0f;
this->actor.floorHeight = this->actor.home.pos.y;
this->actor.gravity = 0.0f;
EnGirlA_SetupAction(this, EnGirlA_Noop);
this->isInitialized = true;
this->actionFunc2 = EnGirlA_Update2;
this->isSelected = false;
this->yRotation = 0;
this->yRotationInit = this->actor.shape.rot.y;
}
}
}

View File

@@ -15,7 +15,7 @@ typedef struct EnGirlA {
/* 0x0000 */ Actor actor;
/* 0x014C */ SkelAnime skelAnime;
/* 0x0190 */ EnGirlAActionFunc actionFunc;
/* 0x0194 */ s8 objBankIndex;
/* 0x0194 */ s8 requiredObjectSlot;
/* 0x0198 */ EnGirlAActionFunc actionFunc2;
/* 0x019C */ s32 isInitialized;
/* 0x01A0 */ s16 itemBuyPromptTextId;
@@ -53,7 +53,7 @@ typedef enum {
/* 0x0D */ SI_DEKU_SHIELD,
/* 0x0E */ SI_GORON_TUNIC,
/* 0x0F */ SI_ZORA_TUNIC,
/* 0x10 */ SI_HEART,
/* 0x10 */ SI_RECOVERY_HEART,
/* 0x11 */ SI_MILK_BOTTLE,
/* 0x12 */ SI_WEIRD_EGG,
/* 0x13 */ SI_19,

View File

@@ -131,7 +131,8 @@ void func_80A89160(EnJs* this, PlayState* play) {
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_CARPET_SALESMAN, true, this)) {
this->actor.parent = NULL;
En_Js_SetupAction(this, func_80A8910C);
Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN);
// Moved into the text handling to patch a text bug, not a great solution though
// Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN);
} else {
GetItemEntry itemEntry = ItemTable_Retrieve(GI_BOMBCHUS_10);
gSaveContext.pendingSale = itemEntry.itemId;
@@ -148,8 +149,14 @@ void func_80A891C4(EnJs* this, PlayState* play) {
Message_ContinueTextbox(play, 0x6075);
func_80A89008(this);
} else {
Rupees_ChangeBy(-200);
En_Js_SetupAction(this, func_80A89160);
if (GameInteractor_Should(VB_GIVE_BOMBCHUS_FROM_CARPET_SALESMAN, true, this) ||
(Actor_HasParent(&this->actor, play) || !GameInteractor_Should(VB_GIVE_ITEM_FROM_CARPET_SALESMAN, true, this))){
Rupees_ChangeBy(-200);
En_Js_SetupAction(this, func_80A89160);
} else{
Message_ContinueTextbox(play, 0x6073);
func_80A89008(this);
}
}
break;
case 1: // no

View File

@@ -206,7 +206,7 @@ ShopItem sShopkeeperStores[][8] = {
{ SI_DEKU_SEEDS_30, -50, 52, -20 },
{ SI_ARROWS_10, -50, 76, -20 },
{ SI_ARROWS_30, -80, 52, -3 },
{ SI_HEART, -80, 76, -3 } },
{ SI_RECOVERY_HEART, -80, 76, -3 } },
{ { SI_GREEN_POTION, 50, 52, -20 },
{ SI_BLUE_FIRE, 50, 76, -20 },
@@ -238,7 +238,7 @@ ShopItem sShopkeeperStores[][8] = {
{ { SI_HYLIAN_SHIELD, 50, 52, -20 },
{ SI_BOMBS_5_R35, 50, 76, -20 },
{ SI_DEKU_NUTS_5, 80, 52, -3 },
{ SI_HEART, 80, 76, -3 },
{ SI_RECOVERY_HEART, 80, 76, -3 },
{ SI_ARROWS_10, -50, 52, -20 },
{ SI_ARROWS_50, -50, 76, -20 },
{ SI_DEKU_STICK, -80, 52, -3 },
@@ -247,7 +247,7 @@ ShopItem sShopkeeperStores[][8] = {
{ { SI_HYLIAN_SHIELD, 50, 52, -20 },
{ SI_BOMBS_5_R25, 50, 76, -20 },
{ SI_DEKU_NUTS_5, 80, 52, -3 },
{ SI_HEART, 80, 76, -3 },
{ SI_RECOVERY_HEART, 80, 76, -3 },
{ SI_ARROWS_10, -50, 52, -20 },
{ SI_ARROWS_50, -50, 76, -20 },
{ SI_DEKU_STICK, -80, 52, -3 },
@@ -256,15 +256,15 @@ ShopItem sShopkeeperStores[][8] = {
{ { SI_MILK_BOTTLE, 50, 52, -20 },
{ SI_DEKU_NUTS_5, 50, 76, -20 },
{ SI_DEKU_NUTS_10, 80, 52, -3 },
{ SI_HEART, 80, 76, -3 },
{ SI_RECOVERY_HEART, 80, 76, -3 },
{ SI_WEIRD_EGG, -50, 52, -20 },
{ SI_DEKU_STICK, -50, 76, -20 },
{ SI_HEART, -80, 52, -3 },
{ SI_HEART, -80, 76, -3 } },
{ SI_RECOVERY_HEART, -80, 52, -3 },
{ SI_RECOVERY_HEART, -80, 76, -3 } },
{ { SI_ZORA_TUNIC, 50, 52, -20 },
{ SI_ARROWS_10, 50, 76, -20 },
{ SI_HEART, 80, 52, -3 },
{ SI_RECOVERY_HEART, 80, 52, -3 },
{ SI_ARROWS_30, 80, 76, -3 },
{ SI_DEKU_NUTS_5, -50, 52, -20 },
{ SI_ARROWS_50, -50, 76, -20 },
@@ -276,9 +276,9 @@ ShopItem sShopkeeperStores[][8] = {
{ SI_BOMBS_20, 80, 52, -3 },
{ SI_BOMBS_30, 80, 76, -3 },
{ SI_GORON_TUNIC, -50, 52, -20 },
{ SI_HEART, -50, 76, -20 },
{ SI_RECOVERY_HEART, -50, 76, -20 },
{ SI_RED_POTION_R40, -80, 52, -3 },
{ SI_HEART, -80, 76, -3 } },
{ SI_RECOVERY_HEART, -80, 76, -3 } },
{ { SI_19, 50, 52, -20 },
{ SI_19, 50, 76, -20 },