From 107c0288cc46e378c67dc4ae2e39cfd2e5fcbc25 Mon Sep 17 00:00:00 2001 From: Billy <1184136+philtyl@users.noreply.github.com> Date: Wed, 20 Sep 2023 01:41:42 +0000 Subject: [PATCH] Dekunut Salesman Docs (#1493) * Dekunut Salesman Docs * Update src/overlays/actors/ovl_En_Dns/z_en_dns.c Remove extra param from debug logging Co-authored-by: Dragorn421 * * Full Deku/Potion name usage * Dialog -> CanBuy * Revert debug logging symbols * Proper declaration spacing * Fix en_shopnuts header doc * Biz -> Business * Fix missed deku prefix's * Synchronize CanBuy sticks and nuts * Fix enum naming * Clarified CanBuy success values * anon review * fig review * macro changes * fix macro usage --------- Co-authored-by: Dragorn421 Co-authored-by: fig02 --- assets/xml/objects/object_shopnuts.xml | 46 +- include/z64save.h | 6 +- src/overlays/actors/ovl_En_Dns/z_en_dns.c | 410 ++++++++++-------- src/overlays/actors/ovl_En_Dns/z_en_dns.h | 47 +- .../actors/ovl_En_Nutsball/z_en_nutsball.c | 8 +- .../actors/ovl_En_Nutsball/z_en_nutsball.h | 10 + .../actors/ovl_En_Shopnuts/z_en_shopnuts.c | 91 ++-- .../actors/ovl_En_Shopnuts/z_en_shopnuts.h | 8 +- 8 files changed, 363 insertions(+), 263 deletions(-) diff --git a/assets/xml/objects/object_shopnuts.xml b/assets/xml/objects/object_shopnuts.xml index a4e12e38ac..105ce88247 100644 --- a/assets/xml/objects/object_shopnuts.xml +++ b/assets/xml/objects/object_shopnuts.xml @@ -1,26 +1,26 @@ - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -54,14 +54,14 @@ - - + + - - - + + + diff --git a/include/z64save.h b/include/z64save.h index 3e006fa1ef..4b2ca8e41b 100644 --- a/include/z64save.h +++ b/include/z64save.h @@ -580,7 +580,7 @@ typedef enum { #define ITEMGETINF_08 0x08 #define ITEMGETINF_09 0x09 #define ITEMGETINF_0A 0x0A -#define ITEMGETINF_0B 0x0B +#define ITEMGETINF_DEKU_HEART_PIECE 0x0B #define ITEMGETINF_0C 0x0C #define ITEMGETINF_0D 0x0D #define ITEMGETINF_0E 0x0E @@ -750,8 +750,8 @@ typedef enum { #define INFTABLE_17F 0x17F #define INFTABLE_190 0x190 #define INFTABLE_191 0x191 -#define INFTABLE_192 0x192 -#define INFTABLE_193 0x193 +#define INFTABLE_HAS_DEKU_STICK_UPGRADE 0x192 +#define INFTABLE_HAS_DEKU_NUT_UPGRADE 0x193 #define INFTABLE_195 0x195 #define INFTABLE_196 0x196 #define INFTABLE_197 0x197 diff --git a/src/overlays/actors/ovl_En_Dns/z_en_dns.c b/src/overlays/actors/ovl_En_Dns/z_en_dns.c index 124bf4e0eb..67727d95fe 100644 --- a/src/overlays/actors/ovl_En_Dns/z_en_dns.c +++ b/src/overlays/actors/ovl_En_Dns/z_en_dns.c @@ -1,11 +1,10 @@ /* * File: z_en_dns.c * Overlay: En_Dns - * Description: Deku Salesman + * Description: Deku Salesman - Sale Phase */ #include "z_en_dns.h" -#include "assets/objects/object_shopnuts/object_shopnuts.h" #include "terminal.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3) @@ -15,33 +14,33 @@ void EnDns_Destroy(Actor* thisx, PlayState* play); void EnDns_Update(Actor* thisx, PlayState* play); void EnDns_Draw(Actor* thisx, PlayState* play); -u32 func_809EF5A4(EnDns* this); -u32 func_809EF658(EnDns* this); -u32 func_809EF70C(EnDns* this); -u32 func_809EF73C(EnDns* this); -u32 func_809EF800(EnDns* this); -u32 func_809EF854(EnDns* this); -u32 func_809EF8F4(EnDns* this); -u32 func_809EF9A4(EnDns* this); +u32 EnDns_CanBuyPrice(EnDns* this); +u32 EnDns_CanBuyDekuNuts(EnDns* this); +u32 EnDns_CanBuyDekuSticks(EnDns* this); +u32 EnDns_CanBuyDekuSeeds(EnDns* this); +u32 EnDns_CanBuyDekuShield(EnDns* this); +u32 EnDns_CanBuyBombs(EnDns* this); +u32 EnDns_CanBuyArrows(EnDns* this); +u32 EnDns_CanBuyBottle(EnDns* this); -void func_809EF9F8(EnDns* this); -void func_809EFA28(EnDns* this); -void func_809EFA58(EnDns* this); -void func_809EFA9C(EnDns* this); -void func_809EFACC(EnDns* this); -void func_809EFAFC(EnDns* this); -void func_809EFB40(EnDns* this); +void EnDns_PayPrice(EnDns* this); +void EnDns_PayForDekuNuts(EnDns* this); +void EnDns_PayForHeartPiece(EnDns* this); +void EnDns_PayForBombs(EnDns* this); +void EnDns_PayForArrows(EnDns* this); +void EnDns_PayForDekuStickUpgrade(EnDns* this); +void EnDns_PayForDekuNutUpgrade(EnDns* this); -void EnDns_SetupWait(EnDns* this, PlayState* play); -void EnDns_Wait(EnDns* this, PlayState* play); +void EnDns_SetupIdle(EnDns* this, PlayState* play); +void EnDns_Idle(EnDns* this, PlayState* play); void EnDns_Talk(EnDns* this, PlayState* play); -void func_809EFDD0(EnDns* this, PlayState* play); -void func_809EFEE8(EnDns* this, PlayState* play); -void func_809EFF50(EnDns* this, PlayState* play); -void func_809EFF98(EnDns* this, PlayState* play); -void func_809F008C(EnDns* this, PlayState* play); +void EnDns_OfferSaleItem(EnDns* this, PlayState* play); +void EnDns_SetupSale(EnDns* this, PlayState* play); +void EnDns_Sale(EnDns* this, PlayState* play); void EnDns_SetupBurrow(EnDns* this, PlayState* play); +void EnDns_SetupNoSaleBurrow(EnDns* this, PlayState* play); void EnDns_Burrow(EnDns* this, PlayState* play); +void EnDns_PostBurrow(EnDns* this, PlayState* play); ActorInit En_Dns_InitVars = { ACTOR_EN_DNS, @@ -74,44 +73,42 @@ static ColliderCylinderInitType1 sCylinderInit = { { 18, 32, 0, { 0, 0, 0 } }, }; -static u16 D_809F040C[] = { +static u16 sStartingTextIds[] = { 0x10A0, 0x10A1, 0x10A2, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF, 0x10DC, 0x10DD, }; -// Debug text: "sells" { "Deku Nuts", "Deku Sticks", "Piece of Heart", "Deku Seeds", -// "Deku Shield", "Bombs", "Arrows", "Red Potion", -// "Green Potion", "Deku Stick Upgrade", "Deku Nut Upgrade" } -static char* D_809F0424[] = { - "デクの実売り ", "デクの棒売り ", "ハートの欠片売り ", "デクの種売り ", - "デクの盾売り ", "バクダン売り ", "矢売り ", "赤のくすり売り ", - "緑のくすり売り ", "デクの棒持てる数を増やす", "デクの実持てる数を増やす", +static char* sItemDebugTxt[] = { + "デクの実売り ", // "Deku Nuts" + "デクの棒売り ", // "Deku Sticks" + "ハートの欠片売り ", // "Piece of Heart" + "デクの種売り ", // "Deku Seeds" + "デクの盾売り ", // "Deku Shield" + "バクダン売り ", // "Bombs" + "矢売り ", // "Arrows" + "赤のくすり売り ", // "Red Potion" + "緑のくすり売り ", // "Green Potion" + "デクの棒持てる数を増やす", // "Deku Stick Upgrade" + "デクの実持てる数を増やす", // "Deku Nut Upgrade" }; -static DnsItemEntry D_809F0450 = { 20, 5, GI_DEKU_NUTS_5_2, func_809EF5A4, func_809EFA28 }; +static DnsItemEntry sItemDekuNuts = { 20, 5, GI_DEKU_NUTS_5_2, EnDns_CanBuyDekuNuts, EnDns_PayForDekuNuts }; +static DnsItemEntry sItemDekuSticks = { 15, 1, GI_DEKU_STICKS_1, EnDns_CanBuyDekuSticks, EnDns_PayPrice }; +static DnsItemEntry sItemHeartPiece = { 10, 1, GI_HEART_PIECE, EnDns_CanBuyPrice, EnDns_PayForHeartPiece }; +static DnsItemEntry sItemDekuSeeds = { 40, 30, GI_DEKU_SEEDS_30, EnDns_CanBuyDekuSeeds, EnDns_PayPrice }; +static DnsItemEntry sItemDekuShield = { 50, 1, GI_SHIELD_DEKU, EnDns_CanBuyDekuShield, EnDns_PayPrice }; +static DnsItemEntry sItemBombs = { 40, 5, GI_BOMBS_5, EnDns_CanBuyBombs, EnDns_PayForBombs }; +static DnsItemEntry sItemArrows = { 70, 20, GI_ARROWS_30, EnDns_CanBuyArrows, EnDns_PayForArrows }; +static DnsItemEntry sItemRedPotion = { 40, 1, GI_BOTTLE_POTION_RED, EnDns_CanBuyBottle, EnDns_PayPrice }; +static DnsItemEntry sItemGreenPotion = { 40, 1, GI_BOTTLE_POTION_GREEN, EnDns_CanBuyBottle, EnDns_PayPrice }; -static DnsItemEntry D_809F0460 = { 15, 1, GI_DEKU_STICKS_1, func_809EF658, func_809EF9F8 }; - -static DnsItemEntry D_809F0470 = { 10, 1, GI_HEART_PIECE, func_809EF70C, func_809EFA58 }; - -static DnsItemEntry D_809F0480 = { 40, 30, GI_DEKU_SEEDS_30, func_809EF73C, func_809EF9F8 }; - -static DnsItemEntry D_809F0490 = { 50, 1, GI_SHIELD_DEKU, func_809EF800, func_809EF9F8 }; - -static DnsItemEntry D_809F04A0 = { 40, 5, GI_BOMBS_5, func_809EF854, func_809EFA9C }; - -static DnsItemEntry D_809F04B0 = { 70, 20, GI_ARROWS_30, func_809EF8F4, func_809EFACC }; - -static DnsItemEntry D_809F04C0 = { 40, 1, GI_BOTTLE_POTION_RED, func_809EF9A4, func_809EF9F8 }; - -static DnsItemEntry D_809F04D0 = { 40, 1, GI_BOTTLE_POTION_GREEN, func_809EF9A4, func_809EF9F8 }; - -static DnsItemEntry D_809F04E0 = { 40, 1, GI_DEKU_STICK_UPGRADE_20, func_809EF70C, func_809EFAFC }; - -static DnsItemEntry D_809F04F0 = { 40, 1, GI_DEKU_NUT_UPGRADE_30, func_809EF70C, func_809EFB40 }; +static DnsItemEntry sItemDekuStickUpgrade = { 40, 1, GI_DEKU_STICK_UPGRADE_20, EnDns_CanBuyPrice, + EnDns_PayForDekuStickUpgrade }; +static DnsItemEntry sItemDekuNutUpgrade = { 40, 1, GI_DEKU_NUT_UPGRADE_30, EnDns_CanBuyPrice, + EnDns_PayForDekuNutUpgrade }; static DnsItemEntry* sItemEntries[] = { - &D_809F0450, &D_809F0460, &D_809F0470, &D_809F0480, &D_809F0490, &D_809F04A0, - &D_809F04B0, &D_809F04C0, &D_809F04D0, &D_809F04E0, &D_809F04F0, + &sItemDekuNuts, &sItemDekuSticks, &sItemHeartPiece, &sItemDekuSeeds, &sItemDekuShield, &sItemBombs, + &sItemArrows, &sItemRedPotion, &sItemGreenPotion, &sItemDekuStickUpgrade, &sItemDekuNutUpgrade, }; static InitChainEntry sInitChain[] = { @@ -120,51 +117,52 @@ static InitChainEntry sInitChain[] = { ICHAIN_F32(targetArrowOffset, 30, ICHAIN_STOP), }; -typedef enum { - /* 0 */ ENDNS_ANIM_0, - /* 1 */ ENDNS_ANIM_1, - /* 2 */ ENDNS_ANIM_2 -} EnDnsAnimation; - static AnimationMinimalInfo sAnimationInfo[] = { { &gBusinessScrubNervousIdleAnim, ANIMMODE_LOOP, 0.0f }, - { &gBusinessScrubAnim_4404, ANIMMODE_ONCE, 0.0f }, + { &gBusinessScrubLeaveBurrowAnim, ANIMMODE_ONCE, 0.0f }, { &gBusinessScrubNervousTransitionAnim, ANIMMODE_ONCE, 0.0f }, }; void EnDns_Init(Actor* thisx, PlayState* play) { EnDns* this = (EnDns*)thisx; - if (this->actor.params < 0) { + if (DNS_GET_TYPE(&this->actor) < 0) { // "Function Error (Deku Salesman)" osSyncPrintf(VT_FGCOL(RED) "引数エラー(売りナッツ)[ arg_data = %d ]" VT_RST "\n", this->actor.params); Actor_Kill(&this->actor); return; } + // Sell Seeds instead of Arrows if Link is child - if ((this->actor.params == 0x0006) && (LINK_AGE_IN_YEARS == YEARS_CHILD)) { - this->actor.params = 0x0003; + if ((DNS_GET_TYPE(&this->actor) == DNS_TYPE_ARROWS_30) && (LINK_AGE_IN_YEARS == YEARS_CHILD)) { + DNS_GET_TYPE(&this->actor) = DNS_TYPE_DEKU_SEEDS_30; } + // "Deku Salesman" - osSyncPrintf(VT_FGCOL(GREEN) "◆◆◆ 売りナッツ『%s』 ◆◆◆" VT_RST "\n", D_809F0424[this->actor.params], - this->actor.params); + osSyncPrintf(VT_FGCOL(GREEN) "◆◆◆ 売りナッツ『%s』 ◆◆◆" VT_RST "\n", sItemDebugTxt[DNS_GET_TYPE(&this->actor)]); + Actor_ProcessInitChain(&this->actor, sInitChain); + SkelAnime_InitFlex(play, &this->skelAnime, &gBusinessScrubSkel, &gBusinessScrubNervousTransitionAnim, - this->jointTable, this->morphTable, 18); + this->jointTable, this->morphTable, BUSINESS_SCRUB_LIMB_MAX); + Collider_InitCylinder(play, &this->collider); Collider_SetCylinderType1(play, &this->collider, &this->actor, &sCylinderInit); + ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 35.0f); - this->actor.textId = D_809F040C[this->actor.params]; + this->actor.textId = sStartingTextIds[DNS_GET_TYPE(&this->actor)]; Actor_SetScale(&this->actor, 0.01f); + this->actor.colChkInfo.mass = MASS_IMMOVABLE; - this->maintainCollider = 1; - this->standOnGround = 1; - this->dropCollectible = 0; + this->bumpOn = true; + this->standOnGround = true; + this->dropCollectible = false; this->actor.speed = 0.0f; this->actor.velocity.y = 0.0f; this->actor.gravity = -1.0f; - this->dnsItemEntry = sItemEntries[this->actor.params]; - this->actionFunc = EnDns_SetupWait; + this->dnsItemEntry = sItemEntries[DNS_GET_TYPE(&this->actor)]; + + this->actionFunc = EnDns_SetupIdle; } void EnDns_Destroy(Actor* thisx, PlayState* play) { @@ -174,154 +172,175 @@ void EnDns_Destroy(Actor* thisx, PlayState* play) { } void EnDns_ChangeAnim(EnDns* this, u8 index) { - s16 frameCount; + s16 frameCount = Animation_GetLastFrame(sAnimationInfo[index].animation); - frameCount = Animation_GetLastFrame(sAnimationInfo[index].animation); - this->unk_2BA = index; // Not used anywhere else? - Animation_Change(&this->skelAnime, sAnimationInfo[index].animation, 1.0f, 0.0f, (f32)frameCount, + this->animIndex = index; + Animation_Change(&this->skelAnime, sAnimationInfo[index].animation, 1.0f, 0.0f, frameCount, sAnimationInfo[index].mode, sAnimationInfo[index].morphFrames); } /* Item give checking functions */ -u32 func_809EF5A4(EnDns* this) { +u32 EnDns_CanBuyDekuNuts(EnDns* this) { if ((CUR_CAPACITY(UPG_DEKU_NUTS) != 0) && (AMMO(ITEM_DEKU_NUT) >= CUR_CAPACITY(UPG_DEKU_NUTS))) { - return 1; + return DNS_CANBUY_RESULT_CAPACITY_FULL; } + if (gSaveContext.save.info.playerData.rupees < this->dnsItemEntry->itemPrice) { - return 0; + return DNS_CANBUY_RESULT_NEED_RUPEES; } + if (Item_CheckObtainability(ITEM_DEKU_NUT) == ITEM_NONE) { - return 2; + return DNS_CANBUY_RESULT_SUCCESS_NEW_ITEM; } - return 4; + + return DNS_CANBUY_RESULT_SUCCESS; } -u32 func_809EF658(EnDns* this) { +u32 EnDns_CanBuyDekuSticks(EnDns* this) { if ((CUR_CAPACITY(UPG_DEKU_STICKS) != 0) && (AMMO(ITEM_DEKU_STICK) >= CUR_CAPACITY(UPG_DEKU_STICKS))) { - return 1; + return DNS_CANBUY_RESULT_CAPACITY_FULL; } + if (gSaveContext.save.info.playerData.rupees < this->dnsItemEntry->itemPrice) { - return 0; + return DNS_CANBUY_RESULT_NEED_RUPEES; } + if (Item_CheckObtainability(ITEM_DEKU_STICK) == ITEM_NONE) { - return 2; + return DNS_CANBUY_RESULT_SUCCESS_NEW_ITEM; } - return 4; + + return DNS_CANBUY_RESULT_SUCCESS; } -u32 func_809EF70C(EnDns* this) { +u32 EnDns_CanBuyPrice(EnDns* this) { if (gSaveContext.save.info.playerData.rupees < this->dnsItemEntry->itemPrice) { - return 0; + return DNS_CANBUY_RESULT_NEED_RUPEES; } - return 4; + + return DNS_CANBUY_RESULT_SUCCESS; } -u32 func_809EF73C(EnDns* this) { +u32 EnDns_CanBuyDekuSeeds(EnDns* this) { if (INV_CONTENT(ITEM_SLINGSHOT) == ITEM_NONE) { - return 3; + return DNS_CANBUY_RESULT_CANT_GET_NOW; } + if (AMMO(ITEM_SLINGSHOT) >= CUR_CAPACITY(UPG_BULLET_BAG)) { - return 1; + return DNS_CANBUY_RESULT_CAPACITY_FULL; } + if (gSaveContext.save.info.playerData.rupees < this->dnsItemEntry->itemPrice) { - return 0; + return DNS_CANBUY_RESULT_NEED_RUPEES; } + if (Item_CheckObtainability(ITEM_DEKU_SEEDS) == ITEM_NONE) { - return 2; + return DNS_CANBUY_RESULT_SUCCESS_NEW_ITEM; } - return 4; + + return DNS_CANBUY_RESULT_SUCCESS; } -u32 func_809EF800(EnDns* this) { +u32 EnDns_CanBuyDekuShield(EnDns* this) { if (CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, EQUIP_INV_SHIELD_DEKU)) { - return 1; + return DNS_CANBUY_RESULT_CAPACITY_FULL; } + if (gSaveContext.save.info.playerData.rupees < this->dnsItemEntry->itemPrice) { - return 0; + return DNS_CANBUY_RESULT_NEED_RUPEES; } - return 4; + + return DNS_CANBUY_RESULT_SUCCESS; } -u32 func_809EF854(EnDns* this) { +u32 EnDns_CanBuyBombs(EnDns* this) { if (!CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) { - return 3; + return DNS_CANBUY_RESULT_CANT_GET_NOW; } + if (AMMO(ITEM_BOMB) >= CUR_CAPACITY(UPG_BOMB_BAG)) { - return 1; + return DNS_CANBUY_RESULT_CAPACITY_FULL; } + if (gSaveContext.save.info.playerData.rupees < this->dnsItemEntry->itemPrice) { - return 0; + return DNS_CANBUY_RESULT_NEED_RUPEES; } - return 4; + + return DNS_CANBUY_RESULT_SUCCESS; } -u32 func_809EF8F4(EnDns* this) { +u32 EnDns_CanBuyArrows(EnDns* this) { if (Item_CheckObtainability(ITEM_BOW) == ITEM_NONE) { - return 3; + return DNS_CANBUY_RESULT_CANT_GET_NOW; } + if (AMMO(ITEM_BOW) >= CUR_CAPACITY(UPG_QUIVER)) { - return 1; + return DNS_CANBUY_RESULT_CAPACITY_FULL; } + if (gSaveContext.save.info.playerData.rupees < this->dnsItemEntry->itemPrice) { - return 0; + return DNS_CANBUY_RESULT_NEED_RUPEES; } - return 4; + + return DNS_CANBUY_RESULT_SUCCESS; } -u32 func_809EF9A4(EnDns* this) { +u32 EnDns_CanBuyBottle(EnDns* this) { if (!Inventory_HasEmptyBottle()) { - return 1; + return DNS_CANBUY_RESULT_CAPACITY_FULL; } + if (gSaveContext.save.info.playerData.rupees < this->dnsItemEntry->itemPrice) { - return 0; + return DNS_CANBUY_RESULT_NEED_RUPEES; } - return 4; + + return DNS_CANBUY_RESULT_SUCCESS; } /* Paying and flagging functions */ -void func_809EF9F8(EnDns* this) { +void EnDns_PayPrice(EnDns* this) { Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); } -void func_809EFA28(EnDns* this) { +void EnDns_PayForDekuNuts(EnDns* this) { Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); } -void func_809EFA58(EnDns* this) { - SET_ITEMGETINF(ITEMGETINF_0B); +void EnDns_PayForHeartPiece(EnDns* this) { + SET_ITEMGETINF(ITEMGETINF_DEKU_HEART_PIECE); Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); } -void func_809EFA9C(EnDns* this) { +void EnDns_PayForBombs(EnDns* this) { Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); } -void func_809EFACC(EnDns* this) { +void EnDns_PayForArrows(EnDns* this) { Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); } -void func_809EFAFC(EnDns* this) { - SET_INFTABLE(INFTABLE_192); +void EnDns_PayForDekuStickUpgrade(EnDns* this) { + SET_INFTABLE(INFTABLE_HAS_DEKU_STICK_UPGRADE); Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); } -void func_809EFB40(EnDns* this) { - SET_INFTABLE(INFTABLE_193); +void EnDns_PayForDekuNutUpgrade(EnDns* this) { + SET_INFTABLE(INFTABLE_HAS_DEKU_NUT_UPGRADE); Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); } -void EnDns_SetupWait(EnDns* this, PlayState* play) { +void EnDns_SetupIdle(EnDns* this, PlayState* play) { if (this->skelAnime.curFrame == this->skelAnime.endFrame) { - this->actionFunc = EnDns_Wait; - EnDns_ChangeAnim(this, ENDNS_ANIM_0); + this->actionFunc = EnDns_Idle; + EnDns_ChangeAnim(this, DNS_ANIM_IDLE); } } -void EnDns_Wait(EnDns* this, PlayState* play) { +void EnDns_Idle(EnDns* this, PlayState* play) { Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 2000, 0); this->actor.world.rot.y = this->actor.shape.rot.y; + if (Actor_ProcessTalkRequest(&this->actor, play)) { this->actionFunc = EnDns_Talk; } else { @@ -340,41 +359,45 @@ void EnDns_Talk(EnDns* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) { switch (play->msgCtx.choiceIndex) { case 0: // OK - switch (this->dnsItemEntry->purchaseableCheck(this)) { - case 0: + switch (this->dnsItemEntry->canBuy(this)) { + case DNS_CANBUY_RESULT_NEED_RUPEES: Message_ContinueTextbox(play, 0x10A5); - this->actionFunc = func_809F008C; + this->actionFunc = EnDns_SetupNoSaleBurrow; break; - case 1: + + case DNS_CANBUY_RESULT_CAPACITY_FULL: Message_ContinueTextbox(play, 0x10A6); - this->actionFunc = func_809F008C; + this->actionFunc = EnDns_SetupNoSaleBurrow; break; - case 3: + + case DNS_CANBUY_RESULT_CANT_GET_NOW: Message_ContinueTextbox(play, 0x10DE); - this->actionFunc = func_809F008C; + this->actionFunc = EnDns_SetupNoSaleBurrow; break; - case 2: - case 4: + + case DNS_CANBUY_RESULT_SUCCESS_NEW_ITEM: + case DNS_CANBUY_RESULT_SUCCESS: Message_ContinueTextbox(play, 0x10A7); - this->actionFunc = func_809EFEE8; + this->actionFunc = EnDns_SetupSale; break; } break; - case 1: // No way + + case 1: // "No" Message_ContinueTextbox(play, 0x10A4); - this->actionFunc = func_809F008C; + this->actionFunc = EnDns_SetupNoSaleBurrow; } } } -void func_809EFDD0(EnDns* this, PlayState* play) { - if (this->actor.params == 0x9) { +void EnDns_OfferSaleItem(EnDns* this, PlayState* play) { + if (DNS_GET_TYPE(&this->actor) == DNS_TYPE_DEKU_STICK_UPGRADE) { if (CUR_UPG_VALUE(UPG_DEKU_STICKS) < 2) { Actor_OfferGetItem(&this->actor, play, GI_DEKU_STICK_UPGRADE_20, 130.0f, 100.0f); } else { Actor_OfferGetItem(&this->actor, play, GI_DEKU_STICK_UPGRADE_30, 130.0f, 100.0f); } - } else if (this->actor.params == 0xA) { + } else if (DNS_GET_TYPE(&this->actor) == DNS_TYPE_DEKU_NUT_UPGRADE) { if (CUR_UPG_VALUE(UPG_DEKU_NUTS) < 2) { Actor_OfferGetItem(&this->actor, play, GI_DEKU_NUT_UPGRADE_30, 130.0f, 100.0f); } else { @@ -385,84 +408,85 @@ void func_809EFDD0(EnDns* this, PlayState* play) { } } -void func_809EFEE8(EnDns* this, PlayState* play) { +void EnDns_SetupSale(EnDns* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - func_809EFDD0(this, play); - this->actionFunc = func_809EFF50; + EnDns_OfferSaleItem(this, play); + this->actionFunc = EnDns_Sale; } } -void func_809EFF50(EnDns* this, PlayState* play) { +void EnDns_Sale(EnDns* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actor.parent = NULL; - this->actionFunc = func_809EFF98; - } else { - func_809EFDD0(this, play); - } -} - -void func_809EFF98(EnDns* this, PlayState* play) { - Player* player = GET_PLAYER(play); - - if (player->stateFlags1 & PLAYER_STATE1_10) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - this->dnsItemEntry->setRupeesAndFlags(this); - this->dropCollectible = 1; - this->maintainCollider = 0; - this->actor.flags &= ~ACTOR_FLAG_0; - EnDns_ChangeAnim(this, ENDNS_ANIM_1); - this->actionFunc = EnDns_SetupBurrow; - } - } else { - this->dnsItemEntry->setRupeesAndFlags(this); - this->dropCollectible = 1; - this->maintainCollider = 0; - this->actor.flags &= ~ACTOR_FLAG_0; - EnDns_ChangeAnim(this, ENDNS_ANIM_1); - this->actionFunc = EnDns_SetupBurrow; - } -} - -void func_809F008C(EnDns* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - this->maintainCollider = 0; - this->actor.flags &= ~ACTOR_FLAG_0; - EnDns_ChangeAnim(this, ENDNS_ANIM_1); this->actionFunc = EnDns_SetupBurrow; + } else { + EnDns_OfferSaleItem(this, play); } } void EnDns_SetupBurrow(EnDns* this, PlayState* play) { - f32 frameCount = Animation_GetLastFrame(&gBusinessScrubAnim_4404); + Player* player = GET_PLAYER(play); - if (this->skelAnime.curFrame == frameCount) { - Actor_PlaySfx(&this->actor, NA_SE_EN_AKINDONUTS_HIDE); + if (player->stateFlags1 & PLAYER_STATE1_10) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + this->dnsItemEntry->payment(this); + this->dropCollectible = true; + this->bumpOn = false; + this->actor.flags &= ~ACTOR_FLAG_0; + EnDns_ChangeAnim(this, DNS_ANIM_BURROW); + this->actionFunc = EnDns_Burrow; + } + } else { + this->dnsItemEntry->payment(this); + this->dropCollectible = true; + this->bumpOn = false; + this->actor.flags &= ~ACTOR_FLAG_0; + EnDns_ChangeAnim(this, DNS_ANIM_BURROW); + this->actionFunc = EnDns_Burrow; + } +} + +void EnDns_SetupNoSaleBurrow(EnDns* this, PlayState* play) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + this->bumpOn = false; + this->actor.flags &= ~ACTOR_FLAG_0; + EnDns_ChangeAnim(this, DNS_ANIM_BURROW); this->actionFunc = EnDns_Burrow; - this->standOnGround = 0; - this->yInitPos = this->actor.world.pos.y; } } void EnDns_Burrow(EnDns* this, PlayState* play) { - f32 depth; + f32 frameCount = Animation_GetLastFrame(&gBusinessScrubLeaveBurrowAnim); + + if (this->skelAnime.curFrame == frameCount) { + Actor_PlaySfx(&this->actor, NA_SE_EN_AKINDONUTS_HIDE); + this->actionFunc = EnDns_PostBurrow; + this->standOnGround = false; + this->yInitPos = this->actor.world.pos.y; + } +} + +void EnDns_PostBurrow(EnDns* this, PlayState* play) { + f32 depthInGround = this->yInitPos - this->actor.world.pos.y; Vec3f initPos; s32 i; - depth = this->yInitPos - this->actor.world.pos.y; if ((this->dustTimer & 3) == 0) { initPos.x = this->actor.world.pos.x; initPos.y = this->yInitPos; initPos.z = this->actor.world.pos.z; func_80028990(play, 20.0f, &initPos); } + this->actor.shape.rot.y += 0x2000; - // Drops only if you bought its item - if (depth > 400.0f) { + + if (depthInGround > 400.0f) { if (this->dropCollectible) { initPos.x = this->actor.world.pos.x; initPos.y = this->yInitPos; initPos.z = this->actor.world.pos.z; + for (i = 0; i < 3; i++) { Item_DropCollectible(play, &initPos, ITEM00_RECOVERY_HEART); } @@ -476,16 +500,20 @@ void EnDns_Update(Actor* thisx, PlayState* play) { s16 pad; this->dustTimer++; - this->actor.textId = D_809F040C[this->actor.params]; + this->actor.textId = sStartingTextIds[DNS_GET_TYPE(&this->actor)]; + Actor_SetFocus(&this->actor, 60.0f); Actor_SetScale(&this->actor, 0.01f); SkelAnime_Update(&this->skelAnime); Actor_MoveXZGravity(&this->actor); + this->actionFunc(this, play); + if (this->standOnGround) { Actor_UpdateBgCheckInfo(play, &this->actor, 20.0f, 20.0f, 20.0f, UPDBGCHECKINFO_FLAG_2); } - if (this->maintainCollider) { + + if (this->bumpOn) { Collider_UpdateCylinder(&this->actor, &this->collider); CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); } diff --git a/src/overlays/actors/ovl_En_Dns/z_en_dns.h b/src/overlays/actors/ovl_En_Dns/z_en_dns.h index 97acf8241a..fe931bec32 100644 --- a/src/overlays/actors/ovl_En_Dns/z_en_dns.h +++ b/src/overlays/actors/ovl_En_Dns/z_en_dns.h @@ -3,31 +3,62 @@ #include "ultra64.h" #include "global.h" +#include "assets/objects/object_shopnuts/object_shopnuts.h" + +#define DNS_GET_TYPE(thisx) ((thisx)->params) + +typedef enum { + /* 0 */ DNS_TYPE_DEKU_NUTS_5, + /* 1 */ DNS_TYPE_DEKU_STICKS_1, + /* 2 */ DNS_TYPE_HEART_PIECE, + /* 3 */ DNS_TYPE_DEKU_SEEDS_30, + /* 4 */ DNS_TYPE_DEKU_SHIELD, + /* 5 */ DNS_TYPE_BOMBS_5, + /* 6 */ DNS_TYPE_ARROWS_30, + /* 7 */ DNS_TYPE_RED_POTION, + /* 8 */ DNS_TYPE_GREEN_POTION, + /* 9 */ DNS_TYPE_DEKU_STICK_UPGRADE, + /* 10 */ DNS_TYPE_DEKU_NUT_UPGRADE +} EnDnsType; + +typedef enum { + /* 0 */ DNS_CANBUY_RESULT_NEED_RUPEES, + /* 1 */ DNS_CANBUY_RESULT_CAPACITY_FULL, + /* 2 */ DNS_CANBUY_RESULT_SUCCESS_NEW_ITEM, + /* 3 */ DNS_CANBUY_RESULT_CANT_GET_NOW, + /* 4 */ DNS_CANBUY_RESULT_SUCCESS +} EnDnsCanBuyResult; + +typedef enum { + /* 0 */ DNS_ANIM_IDLE, + /* 1 */ DNS_ANIM_BURROW, + /* 2 */ DNS_ANIM_IDLE_TRANSITION +} EnDnsAnimation; struct EnDns; typedef void (*EnDnsActionFunc)(struct EnDns*, PlayState*); -typedef u32 (*EnDnsPurchaseableCheck)(struct EnDns*); -typedef void (*EnDnsSetRupeesAndFlags)(struct EnDns*); +typedef u32 (*EnDnsCanBuyFunc)(struct EnDns*); +typedef void (*EnDnsPaymentFunc)(struct EnDns*); typedef struct { /* 0x00 */ s16 itemPrice; /* 0x02 */ u16 itemAmount; /* 0x04 */ s32 getItemId; - /* 0x08 */ EnDnsPurchaseableCheck purchaseableCheck; - /* 0x0C */ EnDnsSetRupeesAndFlags setRupeesAndFlags; + /* 0x08 */ EnDnsCanBuyFunc canBuy; + /* 0x0C */ EnDnsPaymentFunc payment; } DnsItemEntry; // size = 0x10 typedef struct EnDns { /* 0x0000 */ Actor actor; /* 0x014C */ SkelAnime skelAnime; - /* 0x0190 */ Vec3s jointTable[18]; - /* 0x01FC */ Vec3s morphTable[18]; + /* 0x0190 */ Vec3s jointTable[BUSINESS_SCRUB_LIMB_MAX]; + /* 0x01FC */ Vec3s morphTable[BUSINESS_SCRUB_LIMB_MAX]; /* 0x0268 */ EnDnsActionFunc actionFunc; /* 0x026C */ ColliderCylinder collider; /* 0x02B8 */ s16 dustTimer; - /* 0x02BA */ u8 unk_2BA; - /* 0x02BB */ u8 maintainCollider; + /* 0x02BA */ u8 animIndex; // set but not read + /* 0x02BB */ u8 bumpOn; /* 0x02BC */ u8 standOnGround; /* 0x02BD */ u8 dropCollectible; /* 0x02C0 */ DnsItemEntry* dnsItemEntry; diff --git a/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c b/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c index 5df8760582..3e4902057c 100644 --- a/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c +++ b/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.c @@ -69,7 +69,7 @@ void EnNutsball_Init(Actor* thisx, PlayState* play) { ActorShape_Init(&this->actor.shape, 400.0f, ActorShadow_DrawCircle, 13.0f); Collider_InitCylinder(play, &this->collider); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); - this->requiredObjectSlot = Object_GetSlot(&play->objectCtx, sObjectIds[this->actor.params]); + this->requiredObjectSlot = Object_GetSlot(&play->objectCtx, sObjectIds[NUTSBALL_GET_TYPE(&this->actor)]); if (this->requiredObjectSlot < 0) { Actor_Kill(&this->actor); @@ -165,16 +165,16 @@ void EnNutsball_Update(Actor* thisx, PlayState* play) { } void EnNutsball_Draw(Actor* thisx, PlayState* play) { - s32 pad; + EnNutsball* this = (EnNutsball*)thisx; OPEN_DISPS(play->state.gfxCtx, "../z_en_nutsball.c", 327); Gfx_SetupDL_25Opa(play->state.gfxCtx); Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY); - Matrix_RotateZ(thisx->home.rot.z * 9.58738e-05f, MTXMODE_APPLY); + Matrix_RotateZ(this->actor.home.rot.z * 9.58738e-05f, MTXMODE_APPLY); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, "../z_en_nutsball.c", 333), G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, sDLists[thisx->params]); + gSPDisplayList(POLY_OPA_DISP++, sDLists[NUTSBALL_GET_TYPE(&this->actor)]); CLOSE_DISPS(play->state.gfxCtx, "../z_en_nutsball.c", 337); } diff --git a/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.h b/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.h index 4dff4fa555..aaf85a6571 100644 --- a/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.h +++ b/src/overlays/actors/ovl_En_Nutsball/z_en_nutsball.h @@ -4,6 +4,16 @@ #include "ultra64.h" #include "global.h" +#define NUTSBALL_GET_TYPE(thisx) ((thisx)->params) + +typedef enum { + /* 0 */ EN_NUTSBALL_TYPE_DEKUNUTS, + /* 1 */ EN_NUTSBALL_TYPE_HINTNUTS, + /* 2 */ EN_NUTSBALL_TYPE_SHOPNUTS, + /* 3 */ EN_NUTSBALL_TYPE_DNS, + /* 4 */ EN_NUTSBALL_TYPE_DNK +} EnNutsballType; + struct EnNutsball; typedef void (*EnNutsballActionFunc)(struct EnNutsball*, PlayState*); diff --git a/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c b/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c index b6ed3d4ee7..402d932c84 100644 --- a/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c +++ b/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c @@ -1,5 +1,10 @@ +/* + * File: z_en_shopnuts.c + * Overlay: En_Shopnuts + * Description: Deku Salesman - Attack Phase + */ + #include "z_en_shopnuts.h" -#include "assets/objects/object_shopnuts/object_shopnuts.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_2) @@ -8,10 +13,10 @@ void EnShopnuts_Destroy(Actor* thisx, PlayState* play); void EnShopnuts_Update(Actor* thisx, PlayState* play); void EnShopnuts_Draw(Actor* thisx, PlayState* play); -void EnShopnuts_SetupWait(EnShopnuts* this); -void EnShopnuts_Wait(EnShopnuts* this, PlayState* play); +void EnShopnuts_SetupIdle(EnShopnuts* this); +void EnShopnuts_Idle(EnShopnuts* this, PlayState* play); void EnShopnuts_LookAround(EnShopnuts* this, PlayState* play); -void EnShopnuts_Stand(EnShopnuts* this, PlayState* play); +void EnShopnuts_Peek(EnShopnuts* this, PlayState* play); void EnShopnuts_ThrowNut(EnShopnuts* this, PlayState* play); void EnShopnuts_Burrow(EnShopnuts* this, PlayState* play); void EnShopnuts_SpawnSalesman(EnShopnuts* this, PlayState* play); @@ -48,7 +53,7 @@ static ColliderCylinderInit sCylinderInit = { { 20, 40, 0, { 0, 0, 0 } }, }; -static CollisionCheckInfoInit sColChkInfoInit = { 1, 20, 40, 0xFE }; +static CollisionCheckInfoInit sColChkInfoInit = { 1, 20, 40, MASS_HEAVY }; static InitChainEntry sInitChain[] = { ICHAIN_S8(naviEnemyId, NAVI_ENEMY_BUSINESS_SCRUB, ICHAIN_CONTINUE), @@ -61,19 +66,23 @@ void EnShopnuts_Init(Actor* thisx, PlayState* play) { Actor_ProcessInitChain(&this->actor, sInitChain); ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 35.0f); - SkelAnime_InitFlex(play, &this->skelAnime, &gBusinessScrubSkel, &gBusinessScrubAnim_4574, this->jointTable, - this->morphTable, 18); + + SkelAnime_InitFlex(play, &this->skelAnime, &gBusinessScrubSkel, &gBusinessScrubPeekAnim, this->jointTable, + this->morphTable, BUSINESS_SCRUB_LIMB_MAX); + Collider_InitCylinder(play, &this->collider); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit); Collider_UpdateCylinder(&this->actor, &this->collider); - if (((this->actor.params == 0x0002) && GET_ITEMGETINF(ITEMGETINF_0B)) || - ((this->actor.params == 0x0009) && GET_INFTABLE(INFTABLE_192)) || - ((this->actor.params == 0x000A) && GET_INFTABLE(INFTABLE_193))) { + if (((SHOPNUTS_GET_TYPE(&this->actor) == DNS_TYPE_HEART_PIECE) && GET_ITEMGETINF(ITEMGETINF_DEKU_HEART_PIECE)) || + ((SHOPNUTS_GET_TYPE(&this->actor) == DNS_TYPE_DEKU_STICK_UPGRADE) && + GET_INFTABLE(INFTABLE_HAS_DEKU_STICK_UPGRADE)) || + ((SHOPNUTS_GET_TYPE(&this->actor) == DNS_TYPE_DEKU_NUT_UPGRADE) && + GET_INFTABLE(INFTABLE_HAS_DEKU_NUT_UPGRADE))) { Actor_Kill(&this->actor); } else { - EnShopnuts_SetupWait(this); + EnShopnuts_SetupIdle(this); } } @@ -83,12 +92,12 @@ void EnShopnuts_Destroy(Actor* thisx, PlayState* play) { Collider_DestroyCylinder(play, &this->collider); } -void EnShopnuts_SetupWait(EnShopnuts* this) { - Animation_PlayOnceSetSpeed(&this->skelAnime, &gBusinessScrubAnim_139C, 0.0f); +void EnShopnuts_SetupIdle(EnShopnuts* this) { + Animation_PlayOnceSetSpeed(&this->skelAnime, &gBusinessScrubInitialAnim, 0.0f); this->animFlagAndTimer = Rand_S16Offset(100, 50); this->collider.dim.height = 5; this->collider.base.acFlags &= ~AC_ON; - this->actionFunc = EnShopnuts_Wait; + this->actionFunc = EnShopnuts_Idle; } void EnShopnuts_SetupLookAround(EnShopnuts* this) { @@ -98,22 +107,24 @@ void EnShopnuts_SetupLookAround(EnShopnuts* this) { } void EnShopnuts_SetupThrowNut(EnShopnuts* this) { - Animation_PlayOnce(&this->skelAnime, &gBusinessScrubAnim_1EC); + Animation_PlayOnce(&this->skelAnime, &gBusinessScrubThrowNutAnim); this->actionFunc = EnShopnuts_ThrowNut; } -void EnShopnuts_SetupStand(EnShopnuts* this) { - Animation_MorphToLoop(&this->skelAnime, &gBusinessScrubAnim_4574, -3.0f); +void EnShopnuts_SetupPeek(EnShopnuts* this) { + Animation_MorphToLoop(&this->skelAnime, &gBusinessScrubPeekAnim, -3.0f); + if (this->actionFunc == EnShopnuts_ThrowNut) { this->animFlagAndTimer = 2 | 0x1000; // sets timer and flag } else { this->animFlagAndTimer = 1; } - this->actionFunc = EnShopnuts_Stand; + + this->actionFunc = EnShopnuts_Peek; } void EnShopnuts_SetupBurrow(EnShopnuts* this) { - Animation_MorphToPlayOnce(&this->skelAnime, &gBusinessScrubAnim_39C, -5.0f); + Animation_MorphToPlayOnce(&this->skelAnime, &gBusinessScrubPeekBurrowAnim, -5.0f); Actor_PlaySfx(&this->actor, NA_SE_EN_NUTS_DOWN); this->actionFunc = EnShopnuts_Burrow; } @@ -125,15 +136,17 @@ void EnShopnuts_SetupSpawnSalesman(EnShopnuts* this) { this->actionFunc = EnShopnuts_SpawnSalesman; } -void EnShopnuts_Wait(EnShopnuts* this, PlayState* play) { +void EnShopnuts_Idle(EnShopnuts* this, PlayState* play) { s32 hasSlowPlaybackSpeed = false; if (this->skelAnime.playSpeed < 0.5f) { hasSlowPlaybackSpeed = true; } + if (hasSlowPlaybackSpeed && (this->animFlagAndTimer != 0)) { this->animFlagAndTimer--; } + if (Animation_OnFrame(&this->skelAnime, 9.0f)) { this->collider.base.acFlags |= AC_ON; } else if (Animation_OnFrame(&this->skelAnime, 8.0f)) { @@ -149,7 +162,7 @@ void EnShopnuts_Wait(EnShopnuts* this, PlayState* play) { } else if ((this->animFlagAndTimer == 0) && (this->actor.xzDistToPlayer > 320.0f)) { EnShopnuts_SetupLookAround(this); } else { - EnShopnuts_SetupStand(this); + EnShopnuts_SetupPeek(this); } } if (hasSlowPlaybackSpeed && @@ -161,22 +174,27 @@ void EnShopnuts_Wait(EnShopnuts* this, PlayState* play) { void EnShopnuts_LookAround(EnShopnuts* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); + if (Animation_OnFrame(&this->skelAnime, 0.0f) && (this->animFlagAndTimer != 0)) { this->animFlagAndTimer--; } + if ((this->actor.xzDistToPlayer < 120.0f) || (this->animFlagAndTimer == 0)) { EnShopnuts_SetupBurrow(this); } } -void EnShopnuts_Stand(EnShopnuts* this, PlayState* play) { +void EnShopnuts_Peek(EnShopnuts* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); + if (Animation_OnFrame(&this->skelAnime, 0.0f) && (this->animFlagAndTimer != 0)) { this->animFlagAndTimer--; } + if (!(this->animFlagAndTimer & 0x1000)) { Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0xE38); } + if ((this->actor.xzDistToPlayer < 120.0f) || (this->animFlagAndTimer == 0x1000)) { EnShopnuts_SetupBurrow(this); } else if (this->animFlagAndTimer == 0) { @@ -188,16 +206,19 @@ void EnShopnuts_ThrowNut(EnShopnuts* this, PlayState* play) { Vec3f spawnPos; Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0xE38); + if (this->actor.xzDistToPlayer < 120.0f) { EnShopnuts_SetupBurrow(this); } else if (SkelAnime_Update(&this->skelAnime)) { - EnShopnuts_SetupStand(this); + EnShopnuts_SetupPeek(this); } else if (Animation_OnFrame(&this->skelAnime, 6.0f)) { spawnPos.x = this->actor.world.pos.x + (Math_SinS(this->actor.shape.rot.y) * 23.0f); spawnPos.y = this->actor.world.pos.y + 12.0f; spawnPos.z = this->actor.world.pos.z + (Math_CosS(this->actor.shape.rot.y) * 23.0f); + if (Actor_Spawn(&play->actorCtx, play, ACTOR_EN_NUTSBALL, spawnPos.x, spawnPos.y, spawnPos.z, - this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 2) != NULL) { + this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, + EN_NUTSBALL_TYPE_SHOPNUTS) != NULL) { Actor_PlaySfx(&this->actor, NA_SE_EN_NUTS_THROW); } } @@ -205,10 +226,11 @@ void EnShopnuts_ThrowNut(EnShopnuts* this, PlayState* play) { void EnShopnuts_Burrow(EnShopnuts* this, PlayState* play) { if (SkelAnime_Update(&this->skelAnime)) { - EnShopnuts_SetupWait(this); + EnShopnuts_SetupIdle(this); } else { this->collider.dim.height = ((4.0f - CLAMP_MAX(this->skelAnime.curFrame, 4.0f)) * 10.0f) + 5.0f; } + if (Animation_OnFrame(&this->skelAnime, 4.0f)) { this->collider.base.acFlags &= ~AC_ON; } @@ -218,7 +240,7 @@ void EnShopnuts_SpawnSalesman(EnShopnuts* this, PlayState* play) { if (SkelAnime_Update(&this->skelAnime)) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_DNS, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, - this->actor.params); + SHOPNUTS_GET_TYPE(&this->actor)); Actor_Kill(&this->actor); } else { Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0xE38); @@ -239,18 +261,23 @@ void EnShopnuts_Update(Actor* thisx, PlayState* play) { EnShopnuts* this = (EnShopnuts*)thisx; EnShopnuts_ColliderCheck(this, play); + this->actionFunc(this, play); + Actor_UpdateBgCheckInfo(play, &this->actor, 20.0f, this->collider.dim.radius, this->collider.dim.height, UPDBGCHECKINFO_FLAG_2); + if (this->collider.base.acFlags & AC_ON) { CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); } + CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); - if (this->actionFunc == EnShopnuts_Wait) { + + if (this->actionFunc == EnShopnuts_Idle) { Actor_SetFocus(&this->actor, this->skelAnime.curFrame); } else if (this->actionFunc == EnShopnuts_Burrow) { - Actor_SetFocus(&this->actor, - 20.0f - ((this->skelAnime.curFrame * 20.0f) / Animation_GetLastFrame(&gBusinessScrubAnim_39C))); + Actor_SetFocus(&this->actor, 20.0f - ((this->skelAnime.curFrame * 20.0f) / + Animation_GetLastFrame(&gBusinessScrubPeekBurrowAnim))); } else { Actor_SetFocus(&this->actor, 20.0f); } @@ -259,21 +286,21 @@ void EnShopnuts_Update(Actor* thisx, PlayState* play) { s32 EnShopnuts_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { EnShopnuts* this = (EnShopnuts*)thisx; - if ((limbIndex == 9) && (this->actionFunc == EnShopnuts_ThrowNut)) { + if ((limbIndex == BUSINESS_SCRUB_LIMB_NOSE) && (this->actionFunc == EnShopnuts_ThrowNut)) { *dList = NULL; } + return 0; } void EnShopnuts_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { EnShopnuts* this = (EnShopnuts*)thisx; - f32 curFrame; f32 x; f32 y; f32 z; - if ((limbIndex == 9) && (this->actionFunc == EnShopnuts_ThrowNut)) { + if ((limbIndex == BUSINESS_SCRUB_LIMB_NOSE) && (this->actionFunc == EnShopnuts_ThrowNut)) { OPEN_DISPS(play->state.gfxCtx, "../z_en_shopnuts.c", 682); curFrame = this->skelAnime.curFrame; if (curFrame <= 6.0f) { diff --git a/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h b/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h index 6ebfeabf3e..33971269f7 100644 --- a/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h +++ b/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h @@ -3,9 +3,13 @@ #include "ultra64.h" #include "global.h" +#include "overlays/actors/ovl_En_Dns/z_en_dns.h" +#include "overlays/actors/ovl_En_Nutsball/z_en_nutsball.h" struct EnShopnuts; +#define SHOPNUTS_GET_TYPE(thisx) ((thisx)->params) + typedef void (*EnShopnutsActionFunc)(struct EnShopnuts*, PlayState*); typedef struct EnShopnuts { @@ -13,8 +17,8 @@ typedef struct EnShopnuts { /* 0x014C */ SkelAnime skelAnime; /* 0x0190 */ EnShopnutsActionFunc actionFunc; /* 0x0194 */ s16 animFlagAndTimer; // 0x1000 bit denotes that projectile has been thrown - /* 0x0196 */ Vec3s jointTable[18]; - /* 0x0202 */ Vec3s morphTable[18]; + /* 0x0196 */ Vec3s jointTable[BUSINESS_SCRUB_LIMB_MAX]; + /* 0x0202 */ Vec3s morphTable[BUSINESS_SCRUB_LIMB_MAX]; /* 0x0270 */ ColliderCylinder collider; } EnShopnuts; // size = 0x02BC