summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Hensley <hensley.derek58@gmail.com>2021-07-26 19:27:53 -0700
committerGitHub <noreply@github.com>2021-07-26 22:27:53 -0400
commitc774f880e1b033c53e48fc9b438f84fa47836346 (patch)
tree8258f15c9cf9589288a206f9fc27c3ec7e99d00c
parent930d605c5ca2c9b2c753b046cb4860c6edcce586 (diff)
ovl_en_ossan OK and documented (#223)
* Lots of progress, some came for OOT WIP * Some small cleanup * Fix merge conflict * Bring over updated z_en_girla.h * Fix merge error * some cleanup * fix msgcontext and add sfx ids * func_808AAB30 is ugly but it matches * Cleanup * More cleanup and matched func_808AA8E8 * Matched last two functions * Brought over data as a comment * Figured out data, but not late rodata * Document EnOssan * Cleanup * Added ShopItemIds * Cleanup * Switch left and right stick prompts * Remove testing NON_MATCHING define * Cleanup * Add header to .c file * Adjust header * Rename InitCutscenes to GetCutscenes * Cleanup * Cleanup before merge with upstream * More cleanup * Lower case Shopkeeper * More cleanup * More general cleaning * Found the late rodata issue * Format * Rename InitalUpdate * PR suggestions except texture stuff * Texture stuff * Rename Texture typedef to UNK_TEXPTR * One more rename * Remove * from TexturePtr arrays * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update src/overlays/actors/ovl_En_Ossan/z_en_ossan.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> Co-authored-by: Derek Hensley <d.hensley@tempered.io> Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com>
-rw-r--r--include/PR/ultratypes.h1
-rw-r--r--include/functions.h2
-rw-r--r--linker_scripts/code_script.txt5
-rw-r--r--linker_scripts/object_script.txt26
-rw-r--r--src/overlays/actors/ovl_En_GirlA/z_en_girla.h5
-rw-r--r--src/overlays/actors/ovl_En_Ossan/z_en_ossan.c1796
-rw-r--r--src/overlays/actors/ovl_En_Ossan/z_en_ossan.h71
-rw-r--r--tables/functions.txt130
-rw-r--r--tables/variables.txt62
9 files changed, 1863 insertions, 235 deletions
diff --git a/include/PR/ultratypes.h b/include/PR/ultratypes.h
index faa5b51a6..0e6f4cf39 100644
--- a/include/PR/ultratypes.h
+++ b/include/PR/ultratypes.h
@@ -22,6 +22,7 @@ typedef volatile s64 vs64;
typedef float f32;
typedef double f64;
+typedef void* TexturePtr;
typedef long int Mtx_t[4][4];
typedef union {
diff --git a/include/functions.h b/include/functions.h
index d6c20d5d7..ec8953bb1 100644
--- a/include/functions.h
+++ b/include/functions.h
@@ -1671,7 +1671,7 @@ void func_800F0568(GlobalContext* globalCtx, Vec3f* position, s32 param_3, s16 s
// void func_800F0FF0(void);
// void func_800F10AC(void);
// void func_800F112C(void);
-// void func_800F1250(void);
+u16 func_800F1250(GlobalContext* globalCtx, UNK_TYPE arg1);
void func_800F12D0(GlobalContext* globalCtx);
void func_800F1304(GlobalContext* globalCtx, s16 param_2);
void func_800F1374(s32 param_1, s16 param_2);
diff --git a/linker_scripts/code_script.txt b/linker_scripts/code_script.txt
index 47eafe463..e7a006dd9 100644
--- a/linker_scripts/code_script.txt
+++ b/linker_scripts/code_script.txt
@@ -1269,10 +1269,9 @@ SECTIONS
ovl_En_Ossan : AT(RomLocation)
{
build/src/overlays/actors/ovl_En_Ossan/z_en_ossan.o(.text)
- build/asm/overlays/ovl_En_Ossan_data.o(.data)
+ build/src/overlays/actors/ovl_En_Ossan/z_en_ossan.o(.data)
build/src/overlays/actors/ovl_En_Ossan/z_en_ossan.o(.rodata)
- build/asm/overlays/ovl_En_Ossan_rodata.o(.rodata)
- build/asm/overlays/ovl_En_Ossan_late_rodata.o(.rodata)
+ build/src/overlays/actors/ovl_En_Ossan/z_en_ossan_overlay.o(.ovl)
}
SegmentEnd = .;
SegmentSize = SegmentEnd - SegmentStart;
diff --git a/linker_scripts/object_script.txt b/linker_scripts/object_script.txt
index 25c0cc623..892217f32 100644
--- a/linker_scripts/object_script.txt
+++ b/linker_scripts/object_script.txt
@@ -57,7 +57,6 @@ D_0401F740 = 0x0401F740;
D_0401F7C0 = 0x0401F7C0;
D_0401F8C0 = 0x0401F8C0;
-
/* gameplay_dangeon_keep (segment 05) */
D_05018090 = 0x05018090;
D_05017EA0 = 0x05017EA0;
@@ -171,7 +170,6 @@ D_06000228 = 0x06000228;
D_06000A20 = 0x06000A20;
D_06000040 = 0x06000040;
-
/* z_bg_market_step */
D_0601F050 = 0x0601F050;
D_06018DA0 = 0x06018DA0;
@@ -565,6 +563,30 @@ D_06002530 = 0x06002530;
/* z_en_nnh */
D_06001510 = 0x06001510;
+/* z_en_ossan */
+D_06013320 = 0x06013320;
+D_06012C34 = 0x06012C34;
+D_060028A0 = 0x060028A0;
+D_06009D34 = 0x06009D34;
+D_0600CB3C = 0x0600CB3C;
+D_0600DE34 = 0x0600DE34;
+D_0600E3EC = 0x0600E3EC;
+D_0600C58C = 0x0600C58C;
+D_0600F00C = 0x0600F00C;
+D_0600B9D8 = 0x0600B9D8;
+D_0600C26C = 0x0600C26C;
+D_0600D354 = 0x0600D354;
+D_060131FC = 0x060131FC;
+D_0601430C = 0x0601430C;
+D_060138B0 = 0x060138B0;
+D_0600A460 = 0x0600A460;
+D_06006498 = 0x06006498;
+D_06007140 = 0x06007140;
+D_06006D40 = 0x06006D40;
+D_06005BC0 = 0x06005BC0;
+D_06006F18 = 0x06006F18;
+D_06006B18 = 0x06006B18;
+
/* z_en_pametfrog */
D_06000994 = 0x06000994;
D_06001B08 = 0x06001B08;
diff --git a/src/overlays/actors/ovl_En_GirlA/z_en_girla.h b/src/overlays/actors/ovl_En_GirlA/z_en_girla.h
index c9a06e9a9..f73be40b1 100644
--- a/src/overlays/actors/ovl_En_GirlA/z_en_girla.h
+++ b/src/overlays/actors/ovl_En_GirlA/z_en_girla.h
@@ -131,4 +131,9 @@ typedef struct {
/* 0x34 */ s32 isEnabled;
} StickDirectionPrompt; // size = 0x38
+typedef struct ShopItem {
+ /* 0x00 */ s16 shopItemId;
+ /* 0x02 */ Vec3s spawnPos;
+} ShopItem; // size = 0x8;
+
#endif // Z_EN_GIRLA_H
diff --git a/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
index 4471d0539..9af15cc1f 100644
--- a/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
+++ b/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
@@ -1,14 +1,77 @@
+/*
+ * File: z_en_ossan.c
+ * Overlay: ovl_En_Ossan
+ * Description: Trading Post Shop
+ */
+
#include "z_en_ossan.h"
#define FLAGS 0x00000019
#define THIS ((EnOssan*)thisx)
+#define LOOKED_AT_PLAYER 1
+#define END_INTERACTION 2
+
void EnOssan_Init(Actor* thisx, GlobalContext* globalCtx);
void EnOssan_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnOssan_Update(Actor* thisx, GlobalContext* globalCtx);
-#if 0
+void EnOssan_DrawCuriosityShopMan(Actor* thisx, GlobalContext* globalCtx);
+void EnOssan_DrawPartTimeWorker(Actor* thisx, GlobalContext* globalCtx);
+
+void EnOssan_InitCuriosityShopMan(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_InitPartTimeWorker(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_InitShop(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_Idle(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_BeginInteraction(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_Hello(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_SetHaveMet(EnOssan* this);
+void EnOssan_StartShopping(GlobalContext* globalCtx, EnOssan* this);
+void EnOssan_FaceShopkeeper(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_LookToShopkeeperFromShelf(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_TalkToShopkeeper(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_LookToLeftShelf(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_LookToRightShelf(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_BrowseLeftShelf(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_BrowseRightShelf(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_SelectItem(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_BuyItemWithFanfare(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_CannotBuy(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_CanBuy(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_SetupItemPurchased(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_ItemPurchased(EnOssan* this, GlobalContext* globalCtx);
+void EnOssan_ResetItemPosition(EnOssan* this);
+void EnOssan_Blink(EnOssan* this);
+void EnOssan_GetCutscenes(EnOssan* this, GlobalContext* globalCtx);
+
+extern UNK_TYPE D_0401F740;
+extern UNK_TYPE D_0401F8C0;
+extern UNK_TYPE D_0401F7C0;
+extern FlexSkeletonHeader D_06013320;
+extern AnimationHeader D_06012C34;
+extern FlexSkeletonHeader D_060028A0;
+extern AnimationHeader D_06009D34;
+extern AnimationHeader D_0600CB3C;
+extern AnimationHeader D_0600DE34;
+extern AnimationHeader D_0600E3EC;
+extern AnimationHeader D_0600C58C;
+extern AnimationHeader D_0600F00C;
+extern AnimationHeader D_0600B9D8;
+extern AnimationHeader D_0600C26C;
+extern AnimationHeader D_0600D354;
+extern AnimationHeader D_060131FC;
+extern AnimationHeader D_0601430C;
+extern AnimationHeader D_060138B0;
+extern AnimationHeader D_0600A460;
+extern TexturePtr D_06006498;
+extern TexturePtr D_06007140;
+extern TexturePtr D_06006D40;
+extern TexturePtr D_06005BC0;
+extern TexturePtr D_06006F18;
+extern TexturePtr D_06006B18;
+
+
const ActorInit En_Ossan_InitVars = {
ACTOR_EN_OSSAN,
ACTORCAT_NPC,
@@ -21,148 +84,1625 @@ const ActorInit En_Ossan_InitVars = {
(ActorFunc)NULL,
};
-
-// static InitChainEntry sInitChain[] = {
-static InitChainEntry D_808AC288[] = {
- ICHAIN_F32(targetArrowOffset, 500, ICHAIN_STOP),
+static ActorAnimationEntryS sAnimationsCuriosityShopMan[] = {
+ { &D_06012C34, 1.0f, 0, -1, 0, 0 }, { &D_060131FC, 1.0f, 0, -1, 0, 0 }, { &D_0600C58C, 1.0f, 0, -1, 2, 0 },
+ { &D_0600C58C, -1.0f, 0, -1, 2, 0 }, { &D_0600E3EC, 1.0f, 0, -1, 2, 0 }, { &D_0600F00C, 1.0f, 0, -1, 0, 0 },
+ { &D_0600CB3C, 1.0f, 0, -1, 2, 0 }, { &D_0600D354, 1.0f, 0, -1, 0, 0 }, { &D_060138B0, 1.0f, 0, -1, 2, 0 },
+ { &D_0601430C, 1.0f, 0, -1, 0, 0 }, { &D_0600B9D8, 1.0f, 0, -1, 2, 0 }, { &D_0600C26C, 1.0f, 0, -1, 0, 0 },
+ { &D_0600DE34, 1.0f, 0, -1, 2, 0 },
};
+static ActorAnimationEntryS sAnimationsPartTimeWorker[] = {
+ { &D_06009D34, 1.0f, 0, -1, 0, -10 }, { &D_06009D34, 1.0f, 0, -1, 0, -10 }, { &D_06009D34, 1.0f, 0, -1, 2, 0 },
+ { &D_06009D34, -1.0f, 0, -1, 2, 0 }, { &D_06009D34, 1.0f, 0, -1, 2, 0 }, { &D_06009D34, 1.0f, 0, -1, 0, 0 },
+ { &D_06009D34, 1.0f, 0, -1, 2, 0 }, { &D_06009D34, 1.0f, 0, -1, 0, 0 }, { &D_0600A460, 1.0f, 0, -1, 2, -5 },
+ { &D_0600A460, 1.0f, 0, -1, 0, -5 }, { &D_06009D34, 1.0f, 0, -1, 2, 0 }, { &D_06009D34, 1.0f, 0, -1, 0, 0 },
+};
-extern InitChainEntry D_808AC288[];
-#endif
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A80A0.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A80AC.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A812C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A8218.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A82F4.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/EnOssan_Init.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/EnOssan_Destroy.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A849C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A8500.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A85FC.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A8644.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A86A8.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A8708.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A875C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A8798.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A890C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A8B74.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A8CC0.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A8DF8.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A8E84.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A8EEC.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A90A4.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A91B4.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A935C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A9400.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A94FC.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A95F8.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A980C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A98E4.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A9AB8.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A9C8C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A9D64.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A9E20.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A9E5C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808A9E98.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA0C8.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA1B0.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA224.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA2C8.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA33C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA404.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA5E8.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA6D8.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA79C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA7C0.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA85C.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AA8E8.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AAA64.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AAB30.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AACE0.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AAD14.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AADB4.asm")
-
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AAE1C.asm")
+static s16 sObjectIds[] = { OBJECT_FSN, OBJECT_ANI };
+
+static ActorAnimationEntryS* sAnimations[] = { sAnimationsCuriosityShopMan, sAnimationsPartTimeWorker };
+
+static f32 sActorScales[] = { 0.01f, 0.01f };
+
+static ShopItem sShops[][8] = {
+ { { SI_NUTS_1, { 50, 68, -195 } },
+ { SI_STICK_1, { 50, 92, -195 } },
+ { SI_ARROWS_LARGE_1, { 80, 68, -195 } },
+ { SI_ARROWS_MEDIUM_1, { 80, 92, -195 } },
+ { SI_FAIRY_1, { -50, 68, -195 } },
+ { SI_POTION_GREEN_2, { -50, 92, -195 } },
+ { SI_SHIELD_HERO_1, { -80, 68, -195 } },
+ { SI_POTION_RED_2, { -80, 92, -195 } } },
+
+ { { SI_NUTS_2, { 50, 68, -195 } },
+ { SI_STICK_2, { 50, 92, -195 } },
+ { SI_ARROWS_LARGE_2, { 80, 68, -195 } },
+ { SI_ARROWS_MEDIUM_2, { 80, 92, -195 } },
+ { SI_FAIRY_2, { -50, 68, -195 } },
+ { SI_POTION_GREEN_3, { -50, 92, -195 } },
+ { SI_SHIELD_HERO_2, { -80, 68, -195 } },
+ { SI_POTION_RED_3, { -80, 92, -195 } } },
+};
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AAE84.asm")
+static u16 sWelcomeHumanTextIds[] = { 0X06A4, 0X06C1 };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AAFB0.asm")
+static u16 sTalkOptionTextIds[] = { 0X06AB, 0X06C8 };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AB0B0.asm")
+static u16 sWelcomeGoronFirstTimeTextIds[] = { 0X06A5, 0X06C2 };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AB16C.asm")
+static u16 sWelcomeZoraFirstTimeTextIds[] = { 0X06A7, 0X06C4 };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AB404.asm")
+static u16 sWelcomeDekuFirstTimeTextIds[] = { 0X06A9, 0X06C6 };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/EnOssan_Update.asm")
+static u16 sWelcomeGoronTextIds[] = { 0X06A6, 0X06C3 };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AB52C.asm")
+static u16 sWelcomeZoraTextIds[] = { 0X06A8, 0X06C5 };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AB78C.asm")
+static u16 sWelcomeDekuTextIds[] = { 0X06AA, 0X06C7 };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808AB928.asm")
+static u16 sNeedEmptyBottleTextIds[] = { 0X06BC, 0X06D9 };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808ABCD0.asm")
+static u16 sNeedRupeesTextIds[] = { 0X06BD, 0X06DA };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808ABD10.asm")
+static u16 sNoRoomTextIds[] = { 0X06BE, 0X06DB };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808ABD60.asm")
+static u16 sBuySuccessTextIds[] = { 0X06BF, 0X06DC };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808ABE18.asm")
+static u16 sCannotGetNowTextIds[] = { 0X06C0, 0X06DD };
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808ABE58.asm")
+static InitChainEntry sInitChain[] = {
+ ICHAIN_F32(targetArrowOffset, 500, ICHAIN_STOP),
+};
-#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Ossan_0x808A80A0/func_808ABF30.asm")
+void EnOssan_SetupAction(EnOssan* this, EnOssanActionFunc action) {
+ this->actionFunc = action;
+}
+
+s32 EnOssan_TestItemSelected(GlobalContext* globalCtx) {
+ MessageContext* msgCtx = &globalCtx->msgCtx;
+
+ if (msgCtx->unk12020 == 0x10 || msgCtx->unk12020 == 0x11) {
+ return CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_A);
+ }
+ return CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_A) ||
+ CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_B) ||
+ CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_CUP);
+}
+
+void EnOssan_CheckValidSpawn(EnOssan* this) {
+ switch (gSaveContext.day) {
+ case 1:
+ case 2:
+ if (gSaveContext.time <= CLOCK_TIME(21, 30) && gSaveContext.time > CLOCK_TIME(6, 00)) {
+ if (this->actor.params != ENOSSAN_CURIOSITY_SHOP_MAN) {
+ Actor_MarkForDeath(&this->actor);
+ }
+ } else if (this->actor.params == ENOSSAN_CURIOSITY_SHOP_MAN) {
+ Actor_MarkForDeath(&this->actor);
+ }
+ break;
+ case 3:
+ if (this->actor.params == ENOSSAN_CURIOSITY_SHOP_MAN) {
+ Actor_MarkForDeath(&this->actor);
+ }
+ if (!(gSaveContext.time <= CLOCK_TIME(22, 00) && gSaveContext.time >= CLOCK_TIME(6, 00))) {
+ if (this->actor.params != ENOSSAN_CURIOSITY_SHOP_MAN) {
+ Actor_MarkForDeath(&this->actor);
+ }
+ }
+ break;
+ }
+}
+
+void EnOssan_RotateHead(EnOssan* this, GlobalContext* globalCtx) {
+ Player* player = PLAYER;
+
+ if (this->actor.params == ENOSSAN_PART_TIME_WORKER) {
+ if (player->transformation == PLAYER_FORM_ZORA) {
+ Math_SmoothStepToS(&this->headRotPartTimeWorker.y, this->headRot.y, 3, 2000, 0);
+ } else if (this->flags & LOOKED_AT_PLAYER) {
+ Math_SmoothStepToS(&this->headRotPartTimeWorker.y, 8000, 3, 2000, 0);
+ } else {
+ Math_SmoothStepToS(&this->headRotPartTimeWorker.y, this->headRot.y, 3, 2000, 0);
+ if (ABS_ALT(this->headRotPartTimeWorker.y - this->headRot.y) < 16) {
+ this->flags |= LOOKED_AT_PLAYER;
+ }
+ }
+ }
+}
+
+void EnOssan_SpawnShopItems(EnOssan* this, GlobalContext* globalCtx, ShopItem* shop) {
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(this->items); i++, shop++) {
+ if (shop->shopItemId < 0) {
+ this->items[i] = NULL;
+ } else {
+ this->items[i] = (EnGirlA*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_GIRLA, shop->spawnPos.x,
+ shop->spawnPos.y, shop->spawnPos.z, 0, 0, 0, shop->shopItemId);
+ }
+ }
+}
+
+void EnOssan_Init(Actor* thisx, GlobalContext* globalCtx) {
+ EnOssan* this = THIS;
+ s16 id;
+
+ //! @bug Condition is impossible, params cannot be both greater then 1 AND less then 0.
+ if (this->actor.params > ENOSSAN_PART_TIME_WORKER && this->actor.params < ENOSSAN_CURIOSITY_SHOP_MAN) {
+ Actor_MarkForDeath(&this->actor);
+ return;
+ }
+ id = sObjectIds[this->actor.params];
+ this->objIndex = Object_GetIndex(&globalCtx->objectCtx, id);
+ if (this->objIndex < 0) {
+ Actor_MarkForDeath(&this->actor);
+ return;
+ }
+ EnOssan_CheckValidSpawn(this);
+ Actor_ProcessInitChain(&this->actor, sInitChain);
+ EnOssan_SetupAction(this, EnOssan_InitShop);
+}
+
+void EnOssan_Destroy(Actor* thisx, GlobalContext* globalCtx) {
+ EnOssan* this = THIS;
+
+ Collider_DestroyCylinder(globalCtx, &this->collider);
+}
+
+void EnOssan_UpdateCursorPos(GlobalContext* globalCtx, EnOssan* this) {
+ s16 x;
+ s16 y;
+
+ func_800B8898(globalCtx, &this->items[this->cursorIdx]->actor, &x, &y);
+ this->cursorX = x;
+ this->cursorY = y;
+}
+
+void EnOssan_EndInteraction(GlobalContext* globalCtx, EnOssan* this) {
+ Player* player = PLAYER;
+
+ func_800B84D0(&this->actor, globalCtx);
+ globalCtx->msgCtx.unk11F22 = 0x43;
+ globalCtx->msgCtx.unk12023 = 4;
+ Interface_ChangeAlpha(50);
+ this->drawCursor = 0;
+ this->stickLeftPrompt.isEnabled = false;
+ this->stickRightPrompt.isEnabled = false;
+ player->stateFlags2 &= ~0x20000000;
+ globalCtx->interfaceCtx.unk_222 = 0;
+ globalCtx->interfaceCtx.unk_224 = 0;
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_PLAYING) {
+ ActorCutscene_Stop(this->cutscene);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_STOPPED;
+ }
+ if (this->actor.params == ENOSSAN_CURIOSITY_SHOP_MAN) {
+ // EnOssan_BeginInteraction includes the animation of him turning around, before being set to idle
+ EnOssan_SetupAction(this, EnOssan_BeginInteraction);
+ } else {
+ EnOssan_SetupAction(this, EnOssan_Idle);
+ }
+}
+
+s32 EnOssan_TestEndInteraction(EnOssan* this, GlobalContext* globalCtx, Input* input) {
+ if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ EnOssan_EndInteraction(globalCtx, this);
+ return true;
+ }
+ return false;
+}
+
+s32 EnOssan_TestCancelOption(EnOssan* this, GlobalContext* globalCtx, Input* input) {
+ if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ this->actionFunc = this->tmpActionFunc;
+ func_80151938(globalCtx, this->items[this->cursorIdx]->actor.textId);
+ return true;
+ }
+ return false;
+}
+
+void EnOssan_SetupStartShopping(GlobalContext* globalCtx, EnOssan* this, u8 skipHello) {
+ func_8011552C(globalCtx, 0x10);
+ if (!skipHello) {
+ EnOssan_SetupAction(this, EnOssan_Hello);
+ } else {
+ EnOssan_StartShopping(globalCtx, this);
+ }
+}
+
+void EnOssan_StartShopping(GlobalContext* globalCtx, EnOssan* this) {
+ EnOssan_SetupAction(this, EnOssan_FaceShopkeeper);
+ func_80151938(globalCtx, 0x640);
+ func_8011552C(globalCtx, 6);
+ this->stickRightPrompt.isEnabled = true;
+ this->stickLeftPrompt.isEnabled = true;
+}
+
+void EnOssan_SetupLookToShopkeeperFromShelf(GlobalContext* globalCtx, EnOssan* this) {
+ play_sound(NA_SE_SY_CURSOR);
+ this->drawCursor = 0;
+ EnOssan_SetupAction(this, EnOssan_LookToShopkeeperFromShelf);
+}
+
+void EnOssan_Idle(EnOssan* this, GlobalContext* globalCtx) {
+ Player* player = PLAYER;
+
+ func_8013D9C8(globalCtx, this->limbRotTableY, this->limbRotTableZ, 19);
+ if (func_800B84D0(&this->actor, globalCtx)) {
+ player->stateFlags2 |= 0x20000000;
+ EnOssan_SetupAction(this, EnOssan_BeginInteraction);
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_STOPPED) {
+ if (ActorCutscene_GetCurrentIndex() == 0x7C) {
+ ActorCutscene_Stop(0x7C);
+ }
+ this->cutscene = this->lookToShopkeeperCutscene;
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_WAITING;
+ }
+ } else {
+ if (this->actor.xzDistToPlayer < 100.0f &&
+ (player->actor.world.pos.x >= -40.0f && player->actor.world.pos.x <= 40.0f) &&
+ (player->actor.world.pos.z >= -91.0f && player->actor.world.pos.z <= -60.0f)) {
+ func_800B8614(&this->actor, globalCtx, 100.0f);
+ }
+ if (this->actor.params == ENOSSAN_PART_TIME_WORKER) {
+ Math_SmoothStepToS(&this->headRotPartTimeWorker.y, 8000, 3, 2000, 0);
+ }
+ }
+}
+
+void EnOssan_BeginInteraction(EnOssan* this, GlobalContext* globalCtx) {
+ ActorAnimationEntryS* animations = sAnimations[this->actor.params];
+ s16 curFrame = this->skelAnime.animCurrentFrame;
+ s16 frameCount = SkelAnime_GetFrameCount(&animations[this->animationIdx].animationSeg->common);
+
+ if (this->animationIdx == 3) {
+ frameCount = 0;
+ }
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_WAITING) {
+ if (ActorCutscene_GetCanPlayNext(this->cutscene)) {
+ ActorCutscene_StartAndSetFlag(this->cutscene, &this->actor);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_PLAYING;
+ } else {
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ }
+ }
+ if (this->actor.params == ENOSSAN_CURIOSITY_SHOP_MAN) {
+ if (curFrame == frameCount) {
+ switch (this->animationIdx) {
+ case 1:
+ this->animationIdx = 2;
+ func_8013BC6C(&this->skelAnime, animations, 2);
+ break;
+ case 2:
+ EnOssan_SetHaveMet(this);
+ this->textId = EnOssan_GetWelcomeCuriosityShopMan(this, globalCtx);
+ func_8013BC6C(&this->skelAnime, animations, this->animationIdx);
+ break;
+ case 4:
+ case 6:
+ case 8:
+ case 10:
+ this->animationIdx++;
+ func_8013BC6C(&this->skelAnime, animations, this->animationIdx);
+ func_801518B0(globalCtx, this->textId, &this->actor);
+ EnOssan_SetupStartShopping(globalCtx, this, false);
+ break;
+ case 5:
+ case 7:
+ case 9:
+ case 11:
+ this->animationIdx = 3;
+ func_8013BC6C(&this->skelAnime, animations, 3);
+ break;
+ case 3:
+ this->animationIdx = 1;
+ func_8013BC6C(&this->skelAnime, animations, 1);
+ EnOssan_SetupAction(this, EnOssan_Idle);
+ break;
+ default:
+ this->animationIdx = 1;
+ func_8013BC6C(&this->skelAnime, animations, 1);
+ EnOssan_SetupAction(this, EnOssan_Idle);
+ break;
+ }
+ }
+ } else {
+ EnOssan_SetHaveMet(this);
+ this->textId = EnOssan_GetWelcomePartTimeWorker(this, globalCtx);
+ func_801518B0(globalCtx, this->textId, &this->actor);
+ EnOssan_SetupStartShopping(globalCtx, this, false);
+ }
+}
+
+void EnOssan_UpdateJoystickInputState(GlobalContext* globalCtx, EnOssan* this) {
+ s8 stickX = CONTROLLER1(globalCtx)->rel.stick_x;
+ s8 stickY = CONTROLLER1(globalCtx)->rel.stick_y;
+
+ this->moveHorizontal = this->moveVertical = false;
+
+ if (this->stickAccumX == 0) {
+ if (stickX > 30 || stickX < -30) {
+ this->stickAccumX = stickX;
+ this->moveHorizontal = true;
+ }
+ } else if (stickX <= 30 && stickX >= -30) {
+ this->stickAccumX = 0;
+ } else if ((this->stickAccumX * stickX) < 0) { // Stick has swapped directions
+ this->stickAccumX = stickX;
+ this->moveHorizontal = true;
+ } else {
+ this->stickAccumX += stickX;
+ if (this->stickAccumX > 2000) {
+ this->stickAccumX = 2000;
+ } else if (this->stickAccumX < -2000) {
+ this->stickAccumX = -2000;
+ }
+ }
+ if (this->stickAccumY == 0) {
+ if (stickY > 30 || stickY < -30) {
+ this->stickAccumY = stickY;
+ this->moveVertical = true;
+ }
+ } else if (stickY <= 30 && stickY >= -30) {
+ this->stickAccumY = 0;
+ } else if ((this->stickAccumY * stickY) < 0) { // Stick has swapped directions
+ this->stickAccumY = stickY;
+ this->moveVertical = true;
+ } else {
+ this->stickAccumY += stickY;
+ if (this->stickAccumY > 2000) {
+ this->stickAccumY = 2000;
+ } else if (this->stickAccumY < -2000) {
+ this->stickAccumY = -2000;
+ }
+ }
+}
+
+u8 EnOssan_SetCursorIndexFromNeutral(EnOssan* this, u8 shelfOffset) {
+ u8 i;
+
+ // if cursor is on the top shelf
+ if (this->cursorIdx & 1) {
+ // scan top shelf
+ for (i = shelfOffset + 1; i < shelfOffset + 4; i += 2) {
+ if (this->items[i] != NULL) {
+ return i;
+ }
+ }
+ // scan bottom shelf
+ for (i = shelfOffset; i < shelfOffset + 4; i += 2) {
+ if (this->items[i] != NULL) {
+ return i;
+ }
+ }
+ } else {
+ // scan bottom shelf
+ for (i = shelfOffset; i < shelfOffset + 4; i += 2) {
+ if (this->items[i] != NULL) {
+ return i;
+ }
+ }
+ // scan top shelf
+ for (i = shelfOffset + 1; i < shelfOffset + 4; i += 2) {
+ if (this->items[i] != NULL) {
+ return i;
+ }
+ }
+ }
+ return CURSOR_INVALID;
+}
+
+u8 EnOssan_CursorRight(EnOssan* this, u8 cursorIdx, u8 shelfSlotMin) {
+ u8 end = shelfSlotMin + 4;
+
+ while (cursorIdx >= shelfSlotMin && cursorIdx < end) {
+ cursorIdx -= 2;
+ if (cursorIdx >= shelfSlotMin && cursorIdx < end) {
+ if (this->items[cursorIdx] != NULL) {
+ return cursorIdx;
+ }
+ }
+ }
+ return CURSOR_INVALID;
+}
+
+u8 EnOssan_CursorLeft(EnOssan* this, u8 cursorIdx, u8 shelfSlotMax) {
+ while (cursorIdx < shelfSlotMax) {
+ cursorIdx += 2;
+ if (cursorIdx < shelfSlotMax) {
+ if (this->items[cursorIdx] != NULL) {
+ return cursorIdx;
+ }
+ }
+ }
+ return CURSOR_INVALID;
+}
+
+void EnOssan_Hello(EnOssan* this, GlobalContext* globalCtx) {
+ ActorAnimationEntryS* animations = sAnimations[this->actor.params];
+ u8 talkState = func_80152498(&globalCtx->msgCtx);
+ s32 pad;
+ Player* player = PLAYER;
+
+ EnOssan_RotateHead(this, globalCtx);
+ if (talkState == 5 && func_80147624(globalCtx)) {
+ if (this->animationIdx == 9 && this->actor.params == ENOSSAN_PART_TIME_WORKER) {
+ this->animationIdx = 1;
+ func_8013BC6C(&this->skelAnime, animations, 1);
+ }
+ this->flags &= ~LOOKED_AT_PLAYER;
+ if (player->transformation == PLAYER_FORM_DEKU) {
+ EnOssan_EndInteraction(globalCtx, this);
+ } else if (this->flags & END_INTERACTION) {
+ this->flags &= ~END_INTERACTION;
+ EnOssan_EndInteraction(globalCtx, this);
+ } else if (!EnOssan_TestEndInteraction(this, globalCtx, CONTROLLER1(globalCtx))) {
+ EnOssan_StartShopping(globalCtx, this);
+ } else {
+ return;
+ }
+ }
+ if (talkState == 10 && this->actor.params == ENOSSAN_PART_TIME_WORKER &&
+ player->transformation == PLAYER_FORM_ZORA && func_80147624(globalCtx)) {
+ this->animationIdx = 9;
+ func_8013BC6C(&this->skelAnime, animations, 9);
+ }
+ if (this->animationIdx == 11 && func_801378B8(&this->skelAnime, 18.0f)) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EV_HANKO);
+ }
+}
+
+s32 EnOssan_FacingShopkeeperDialogResult(EnOssan* this, GlobalContext* globalCtx) {
+ ActorAnimationEntryS* animations = sAnimations[this->actor.params];
+ Player* player = PLAYER;
+
+ switch (globalCtx->msgCtx.choiceIndex) {
+ case 0:
+ func_8019F208();
+ if (this->actor.params == ENOSSAN_PART_TIME_WORKER && player->transformation == PLAYER_FORM_ZORA) {
+ this->animationIdx = 9;
+ func_8013BC6C(&this->skelAnime, animations, 9);
+ }
+ EnOssan_SetupAction(this, EnOssan_TalkToShopkeeper);
+ func_80151938(globalCtx, sTalkOptionTextIds[this->actor.params]);
+ func_8011552C(globalCtx, 6);
+ this->stickLeftPrompt.isEnabled = false;
+ this->stickRightPrompt.isEnabled = false;
+ return true;
+ case 1:
+ func_8019F230();
+ EnOssan_EndInteraction(globalCtx, this);
+ return true;
+ }
+ return false;
+}
+
+void EnOssan_FaceShopkeeper(EnOssan* this, GlobalContext* globalCtx) {
+ u8 talkState = func_80152498(&globalCtx->msgCtx);
+ s32 pad;
+ Player* player = PLAYER;
+ u8 cursorIdx;
+
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_STOPPED) {
+ if (ActorCutscene_GetCurrentIndex() == 0x7C) {
+ ActorCutscene_Stop(0x7C);
+ }
+ this->cutscene = this->lookToShopkeeperCutscene;
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_WAITING;
+ } else {
+ if (talkState == 4) {
+ func_8011552C(globalCtx, 6);
+ if (!EnOssan_TestEndInteraction(this, globalCtx, CONTROLLER1(globalCtx)) &&
+ (!func_80147624(globalCtx) || !EnOssan_FacingShopkeeperDialogResult(this, globalCtx))) {
+ if (this->stickAccumX < 0) {
+ cursorIdx = EnOssan_SetCursorIndexFromNeutral(this, 4);
+ if (cursorIdx != CURSOR_INVALID) {
+ this->cursorIdx = cursorIdx;
+ EnOssan_SetupAction(this, EnOssan_LookToLeftShelf);
+ func_8011552C(globalCtx, 6);
+ this->stickLeftPrompt.isEnabled = false;
+ play_sound(NA_SE_SY_CURSOR);
+ }
+ } else if (this->stickAccumX > 0) {
+ cursorIdx = EnOssan_SetCursorIndexFromNeutral(this, 0);
+ if (cursorIdx != CURSOR_INVALID) {
+ this->cursorIdx = cursorIdx;
+ EnOssan_SetupAction(this, EnOssan_LookToRightShelf);
+ func_8011552C(globalCtx, 6);
+ this->stickRightPrompt.isEnabled = false;
+ play_sound(NA_SE_SY_CURSOR);
+ }
+ }
+ } else {
+ return;
+ }
+ }
+ if (this->actor.params == ENOSSAN_PART_TIME_WORKER && player->transformation != PLAYER_FORM_ZORA) {
+ Math_SmoothStepToS(&this->headRotPartTimeWorker.y, 8000, 3, 2000, 0);
+ }
+ }
+}
+
+void EnOssan_TalkToShopkeeper(EnOssan* this, GlobalContext* globalCtx) {
+ ActorAnimationEntryS* animations = sAnimations[this->actor.params];
+
+ if (func_80152498(&globalCtx->msgCtx) == 5 && func_80147624(globalCtx)) {
+ if (this->animationIdx == 9 && this->actor.params == ENOSSAN_PART_TIME_WORKER) {
+ this->animationIdx = 1;
+ func_8013BC6C(&this->skelAnime, animations, 1);
+ }
+ EnOssan_StartShopping(globalCtx, this);
+ }
+}
+
+void EnOssan_LookToLeftShelf(EnOssan* this, GlobalContext* globalCtx) {
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_PLAYING) {
+ ActorCutscene_Stop(this->cutscene);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_STOPPED;
+ }
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_STOPPED) {
+ if (ActorCutscene_GetCurrentIndex() == 0x7C) {
+ ActorCutscene_Stop(0x7C);
+ }
+ this->cutscene = this->lookToLeftShelfCutscene;
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_WAITING;
+ } else {
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_WAITING) {
+ if (ActorCutscene_GetCanPlayNext(this->cutscene)) {
+ ActorCutscene_StartAndSetFlag(this->cutscene, &this->actor);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_PLAYING;
+ EnOssan_UpdateCursorPos(globalCtx, this);
+ EnOssan_SetupAction(this, EnOssan_BrowseLeftShelf);
+ func_80151938(globalCtx, this->items[this->cursorIdx]->actor.textId);
+ } else {
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ }
+ }
+ this->stickAccumX = 0;
+ }
+}
+
+void EnOssan_LookToRightShelf(EnOssan* this, GlobalContext* globalCtx) {
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_PLAYING) {
+ ActorCutscene_Stop(this->cutscene);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_STOPPED;
+ }
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_STOPPED) {
+ if (ActorCutscene_GetCurrentIndex() == 0x7C) {
+ ActorCutscene_Stop(0x7C);
+ }
+ this->cutscene = this->lookToRightShelfCutscene;
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_WAITING;
+ } else {
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_WAITING) {
+ if (ActorCutscene_GetCanPlayNext(this->cutscene)) {
+ ActorCutscene_StartAndSetFlag(this->cutscene, &this->actor);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_PLAYING;
+ EnOssan_UpdateCursorPos(globalCtx, this);
+ EnOssan_SetupAction(this, EnOssan_BrowseRightShelf);
+ func_80151938(globalCtx, this->items[this->cursorIdx]->actor.textId);
+ } else {
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ }
+ }
+ this->stickAccumX = 0;
+ }
+}
+
+void EnOssan_CursorUpDown(EnOssan* this) {
+ u8 curTemp = this->cursorIdx;
+ u8 curScanTemp;
+
+ if (this->stickAccumY < 0) {
+ curTemp &= (u8)~1;
+ if (this->items[curTemp] != NULL) {
+ this->cursorIdx = curTemp;
+ return;
+ }
+ // cursorIdx on right shelf
+ if (curTemp < 4) {
+ curScanTemp = curTemp + 2;
+ if (curScanTemp >= 4) {
+ curScanTemp = 0;
+ }
+ while (curScanTemp != curTemp) {
+ if (this->items[curScanTemp] != NULL) {
+ this->cursorIdx = curScanTemp;
+ return;
+ }
+ curScanTemp += 2;
+ if (curScanTemp >= 4) {
+ curScanTemp = 0;
+ }
+ }
+ } else {
+ // cursorIdx on left shelf
+ curScanTemp = curTemp + 2;
+ if (curScanTemp >= 8) {
+ curScanTemp = 4;
+ }
+ while (curScanTemp != curTemp) {
+ if (this->items[curScanTemp] != NULL) {
+ this->cursorIdx = curScanTemp;
+ return;
+ }
+ curScanTemp += 2;
+ if (curScanTemp >= 8) {
+ curScanTemp = 4;
+ }
+ }
+ }
+ } else if (this->stickAccumY > 0) {
+ curTemp |= 1;
+ if (this->items[curTemp] != NULL) {
+ this->cursorIdx = curTemp;
+ return;
+ }
+ // cursorIdx on right shelf
+ if (curTemp < 4) {
+ curScanTemp = curTemp + 2;
+ if (curScanTemp >= 4) {
+ curScanTemp = 1;
+ }
+ while (curScanTemp != curTemp) {
+ if (this->items[curScanTemp] != NULL) {
+ this->cursorIdx = curScanTemp;
+ return;
+ }
+ curScanTemp += 2;
+ if (curScanTemp >= 4) {
+ curScanTemp = 1;
+ }
+ }
+ } else {
+ // cursorIdx on left shelf
+ curScanTemp = curTemp + 2;
+ if (curScanTemp >= 8) {
+ curScanTemp = 5;
+ }
+ while (curScanTemp != curTemp) {
+ if (this->items[curScanTemp] != NULL) {
+ this->cursorIdx = curScanTemp;
+ return;
+ }
+ curScanTemp += 2;
+ if (curScanTemp >= 8) {
+ curScanTemp = 5;
+ }
+ }
+ }
+ }
+}
+
+s32 EnOssan_HasPlayerSelectedItem(GlobalContext* globalCtx, EnOssan* this, Input* input) {
+ EnGirlA* item = this->items[this->cursorIdx];
+
+ if (EnOssan_TestEndInteraction(this, globalCtx, input)) {
+ return true;
+ }
+ if (EnOssan_TestItemSelected(globalCtx)) {
+ if (!item->isOutOfStock) {
+ this->tmpActionFunc = this->actionFunc;
+ func_80151938(globalCtx, this->items[this->cursorIdx]->choiceTextId);
+ this->stickLeftPrompt.isEnabled = false;
+ this->stickRightPrompt.isEnabled = false;
+ play_sound(NA_SE_SY_DECIDE);
+ this->drawCursor = 0;
+ EnOssan_SetupAction(this, EnOssan_SelectItem);
+ } else {
+ play_sound(NA_SE_SY_ERROR);
+ }
+ return true;
+ }
+ return false;
+}
+
+void EnOssan_BrowseLeftShelf(EnOssan* this, GlobalContext* globalCtx) {
+ u8 talkState = func_80152498(&globalCtx->msgCtx);
+ s32 pad;
+ u8 prevCursorIndex = this->cursorIdx;
+ u8 cursorIdx;
+
+ if (!EnOssan_ReturnItemToShelf(this)) {
+ this->delayTimer = 3;
+ } else if (this->delayTimer != 0) {
+ this->delayTimer--;
+ } else {
+ this->drawCursor = 0xFF;
+ this->stickRightPrompt.isEnabled = true;
+ EnOssan_UpdateCursorPos(globalCtx, this);
+ if (talkState == 5) {
+ func_8011552C(globalCtx, 6);
+ if (!EnOssan_HasPlayerSelectedItem(globalCtx, this, CONTROLLER1(globalCtx))) {
+ if (this->moveHorizontal) {
+ if (this->stickAccumX > 0) {
+ cursorIdx = EnOssan_CursorRight(this, this->cursorIdx, 4);
+ if (cursorIdx != CURSOR_INVALID) {
+ this->cursorIdx = cursorIdx;
+ } else {
+ EnOssan_SetupLookToShopkeeperFromShelf(globalCtx, this);
+ return;
+ }
+ } else if (this->stickAccumX < 0) {
+ cursorIdx = EnOssan_CursorLeft(this, this->cursorIdx, 8);
+ if (cursorIdx != CURSOR_INVALID) {
+ this->cursorIdx = cursorIdx;
+ }
+ }
+ } else {
+ if (this->stickAccumX > 0 && this->stickAccumX > 500) {
+ cursorIdx = EnOssan_CursorRight(this, this->cursorIdx, 4);
+ if (cursorIdx != CURSOR_INVALID) {
+ this->cursorIdx = cursorIdx;
+ } else {
+ EnOssan_SetupLookToShopkeeperFromShelf(globalCtx, this);
+ return;
+ }
+ } else if (this->stickAccumX < 0 && this->stickAccumX < -500) {
+ cursorIdx = EnOssan_CursorLeft(this, this->cursorIdx, 8);
+ if (cursorIdx != CURSOR_INVALID) {
+ this->cursorIdx = cursorIdx;
+ }
+ }
+ }
+ EnOssan_CursorUpDown(this);
+ if (this->cursorIdx != prevCursorIndex) {
+ func_80151938(globalCtx, this->items[this->cursorIdx]->actor.textId);
+ play_sound(NA_SE_SY_CURSOR);
+ }
+ }
+ }
+ }
+}
+
+void EnOssan_BrowseRightShelf(EnOssan* this, GlobalContext* globalCtx) {
+ u8 talkState = func_80152498(&globalCtx->msgCtx);
+ s32 pad;
+ u8 prevCursorIndex = this->cursorIdx;
+ u8 cursorIdx;
+
+ if (!EnOssan_ReturnItemToShelf(this)) {
+ this->delayTimer = 3;
+ } else if (this->delayTimer != 0) {
+ this->delayTimer--;
+ } else {
+ this->drawCursor = 0xFF;
+ this->stickLeftPrompt.isEnabled = true;
+ EnOssan_UpdateCursorPos(globalCtx, this);
+ if (talkState == 5) {
+ func_8011552C(globalCtx, 6);
+ if (!EnOssan_HasPlayerSelectedItem(globalCtx, this, CONTROLLER1(globalCtx))) {
+ if (this->moveHorizontal != 0) {
+ if (this->stickAccumX < 0) {
+ cursorIdx = EnOssan_CursorRight(this, this->cursorIdx, 0);
+ if (cursorIdx != CURSOR_INVALID) {
+ this->cursorIdx = cursorIdx;
+ } else {
+ EnOssan_SetupLookToShopkeeperFromShelf(globalCtx, this);
+ return;
+ }
+ } else if (this->stickAccumX > 0) {
+ cursorIdx = EnOssan_CursorLeft(this, this->cursorIdx, 4);
+ if (cursorIdx != CURSOR_INVALID) {
+ this->cursorIdx = cursorIdx;
+ }
+ }
+ } else {
+ if (this->stickAccumX < 0 && this->stickAccumX < -500) {
+ cursorIdx = EnOssan_CursorRight(this, this->cursorIdx, 0);
+ if (cursorIdx != CURSOR_INVALID) {
+ this->cursorIdx = cursorIdx;
+ } else {
+ EnOssan_SetupLookToShopkeeperFromShelf(globalCtx, this);
+ return;
+ }
+ } else if (this->stickAccumX > 0 && this->stickAccumX > 500) {
+ cursorIdx = EnOssan_CursorLeft(this, this->cursorIdx, 4);
+ if (cursorIdx != CURSOR_INVALID) {
+ this->cursorIdx = cursorIdx;
+ }
+ }
+ }
+ EnOssan_CursorUpDown(this);
+ if (this->cursorIdx != prevCursorIndex) {
+ func_80151938(globalCtx, this->items[this->cursorIdx]->actor.textId);
+ play_sound(NA_SE_SY_CURSOR);
+ }
+ }
+ }
+ }
+}
+
+void EnOssan_LookToShopkeeperFromShelf(EnOssan* this, GlobalContext* globalCtx) {
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_PLAYING) {
+ ActorCutscene_Stop(this->cutscene);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_STOPPED;
+ }
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_STOPPED) {
+ if (ActorCutscene_GetCurrentIndex() == 0x7C) {
+ ActorCutscene_Stop(0x7C);
+ }
+ this->cutscene = this->lookToShopKeeperFromShelfCutscene;
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_WAITING;
+ } else if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_WAITING) {
+ if (ActorCutscene_GetCanPlayNext(this->cutscene)) {
+ ActorCutscene_StartAndSetFlag(this->cutscene, &this->actor);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_PLAYING;
+ EnOssan_UpdateCursorPos(globalCtx, this);
+ EnOssan_StartShopping(globalCtx, this);
+ } else {
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ }
+ }
+}
+
+void EnOssan_SetupBuyItemWithFanfare(GlobalContext* globalCtx, EnOssan* this) {
+ Player* player = PLAYER;
+
+ func_800B8A1C(&this->actor, globalCtx, this->items[this->cursorIdx]->getItemId, 300.0f, 300.0f);
+ globalCtx->msgCtx.unk11F22 = 0x43;
+ globalCtx->msgCtx.unk12023 = 4;
+ player->stateFlags2 &= ~0x20000000;
+ Interface_ChangeAlpha(50);
+ this->drawCursor = 0;
+ EnOssan_SetupAction(this, EnOssan_BuyItemWithFanfare);
+}
+
+void EnOssan_SetupCannotBuy(GlobalContext* globalCtx, EnOssan* this, u16 textId) {
+ func_80151938(globalCtx, textId);
+ EnOssan_SetupAction(this, EnOssan_CannotBuy);
+}
+
+void EnOssan_SetupBuy(GlobalContext* globalCtx, EnOssan* this, u16 textId) {
+ func_80151938(globalCtx, textId);
+ EnOssan_SetupAction(this, EnOssan_CanBuy);
+}
+
+void EnOssan_HandleCanBuyItem(GlobalContext* globalCtx, EnOssan* this) {
+ EnGirlA* item = this->items[this->cursorIdx];
+
+ switch (item->canBuyFunc(globalCtx, item)) {
+ case CANBUY_RESULT_SUCCESS_1:
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_PLAYING) {
+ ActorCutscene_Stop(this->cutscene);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_STOPPED;
+ }
+ func_8019F208();
+ item->buyFanfareFunc(globalCtx, item);
+ EnOssan_SetupBuyItemWithFanfare(globalCtx, this);
+ this->drawCursor = 0;
+ this->shopItemSelectedTween = 0.0f;
+ item->boughtFunc(globalCtx, item);
+ break;
+ case CANBUY_RESULT_SUCCESS_2:
+ func_8019F208();
+ item->buyFunc(globalCtx, item);
+ EnOssan_SetupBuy(globalCtx, this, sBuySuccessTextIds[this->actor.params]);
+ this->drawCursor = 0;
+ this->shopItemSelectedTween = 0.0f;
+ item->boughtFunc(globalCtx, item);
+ break;
+ case CANBUY_RESULT_NO_ROOM:
+ case CANBUY_RESULT_NO_ROOM_2:
+ play_sound(NA_SE_SY_ERROR);
+ EnOssan_SetupCannotBuy(globalCtx, this, sNoRoomTextIds[this->actor.params]);
+ break;
+ case CANBUY_RESULT_NEED_EMPTY_BOTTLE:
+ play_sound(NA_SE_SY_ERROR);
+ EnOssan_SetupCannotBuy(globalCtx, this, sNeedEmptyBottleTextIds[this->actor.params]);
+ break;
+ case CANBUY_RESULT_NEED_RUPEES:
+ play_sound(NA_SE_SY_ERROR);
+ EnOssan_SetupCannotBuy(globalCtx, this, sNeedRupeesTextIds[this->actor.params]);
+ break;
+ case CANBUY_RESULT_CANNOT_GET_NOW_2:
+ play_sound(NA_SE_SY_ERROR);
+ EnOssan_SetupCannotBuy(globalCtx, this, sCannotGetNowTextIds[this->actor.params]);
+ break;
+ case CANBUY_RESULT_CANNOT_GET_NOW:
+ play_sound(NA_SE_SY_ERROR);
+ EnOssan_SetupCannotBuy(globalCtx, this, sNoRoomTextIds[this->actor.params]);
+ break;
+ }
+}
+
+void EnOssan_SelectItem(EnOssan* this, GlobalContext* globalCtx) {
+ u8 talkState = func_80152498(&globalCtx->msgCtx);
+
+ if (EnOssan_TakeItemOffShelf(this) && talkState == 4) {
+ func_8011552C(globalCtx, 6);
+ if (!EnOssan_TestCancelOption(this, globalCtx, CONTROLLER1(globalCtx)) && func_80147624(globalCtx)) {
+ switch (globalCtx->msgCtx.choiceIndex) {
+ case 0:
+ EnOssan_HandleCanBuyItem(globalCtx, this);
+ break;
+ case 1:
+ func_8019F230();
+ this->actionFunc = this->tmpActionFunc;
+ func_80151938(globalCtx, this->items[this->cursorIdx]->actor.textId);
+ break;
+ }
+ }
+ }
+}
+
+void EnOssan_CannotBuy(EnOssan* this, GlobalContext* globalCtx) {
+ if (func_80152498(&globalCtx->msgCtx) == 5 && func_80147624(globalCtx)) {
+ this->actionFunc = this->tmpActionFunc;
+ func_80151938(globalCtx, this->items[this->cursorIdx]->actor.textId);
+ }
+}
+
+void EnOssan_CanBuy(EnOssan* this, GlobalContext* globalCtx) {
+ EnGirlA* item;
+
+ if (func_80152498(&globalCtx->msgCtx) == 5 && func_80147624(globalCtx)) {
+ this->shopItemSelectedTween = 0.0f;
+ EnOssan_ResetItemPosition(this);
+ item = this->items[this->cursorIdx];
+ item->restockFunc(globalCtx, item);
+ this->actionFunc = this->tmpActionFunc;
+ func_80151938(globalCtx, this->items[this->cursorIdx]->actor.textId);
+ }
+}
+
+void EnOssan_BuyItemWithFanfare(EnOssan* this, GlobalContext* globalCtx) {
+ if (Actor_HasParent(&this->actor, globalCtx)) {
+ this->actor.parent = NULL;
+ EnOssan_SetupAction(this, EnOssan_SetupItemPurchased);
+ } else {
+ func_800B8A1C(&this->actor, globalCtx, this->items[this->cursorIdx]->getItemId, 300.0f, 300.0f);
+ }
+}
+
+void EnOssan_SetupItemPurchased(EnOssan* this, GlobalContext* globalCtx) {
+ if (func_80152498(&globalCtx->msgCtx) == 6 && func_80147624(globalCtx)) {
+ globalCtx->msgCtx.unk11F22 = 0x43;
+ globalCtx->msgCtx.unk12023 = 4;
+ EnOssan_SetupAction(this, EnOssan_ItemPurchased);
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_STOPPED) {
+ if (ActorCutscene_GetCurrentIndex() == 0x7C) {
+ ActorCutscene_Stop(0x7C);
+ }
+ this->cutscene = this->lookToShopkeeperCutscene;
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ }
+ func_800B85E0(&this->actor, globalCtx, 400.0f, -1);
+ }
+}
+
+void EnOssan_ContinueShopping(EnOssan* this, GlobalContext* globalCtx) {
+ u8 talkState = func_80152498(&globalCtx->msgCtx);
+ Player* player = PLAYER;
+ EnGirlA* item;
+
+ if (talkState == 4) {
+ func_8011552C(globalCtx, 6);
+ if (func_80147624(globalCtx)) {
+ EnOssan_ResetItemPosition(this);
+ item = this->items[this->cursorIdx];
+ item->restockFunc(globalCtx, item);
+ if (!EnOssan_TestEndInteraction(this, globalCtx, CONTROLLER1(globalCtx))) {
+ switch (globalCtx->msgCtx.choiceIndex) {
+ case 0:
+ func_8019F208();
+ player->actor.shape.rot.y = BINANG_ROT180(player->actor.shape.rot.y);
+ player->stateFlags2 |= 0x20000000;
+ func_801518B0(globalCtx, this->textId, &this->actor);
+ EnOssan_SetupStartShopping(globalCtx, this, true);
+ func_800B85E0(&this->actor, globalCtx, 100.0f, -1);
+ break;
+ case 1:
+ default:
+ func_8019F230();
+ EnOssan_EndInteraction(globalCtx, this);
+ break;
+ }
+ }
+ }
+ } else if (talkState == 5 && func_80147624(globalCtx)) {
+ EnOssan_ResetItemPosition(this);
+ item = this->items[this->cursorIdx];
+ item->restockFunc(globalCtx, item);
+ player->actor.shape.rot.y = BINANG_ROT180(player->actor.shape.rot.y);
+ player->stateFlags2 |= 0x20000000;
+ func_801518B0(globalCtx, this->textId, &this->actor);
+ EnOssan_SetupStartShopping(globalCtx, this, true);
+ func_800B85E0(&this->actor, globalCtx, 100.0f, -1);
+ }
+}
+
+void EnOssan_ItemPurchased(EnOssan* this, GlobalContext* globalCtx) {
+ Player* player = PLAYER;
+
+ if (this->cutsceneState == ENOSSAN_CUTSCENESTATE_STOPPED) {
+ if (ActorCutscene_GetCanPlayNext(this->cutscene)) {
+ ActorCutscene_StartAndSetFlag(this->cutscene, &this->actor);
+ player->stateFlags2 |= 0x20000000;
+ EnOssan_SetupAction(this, EnOssan_ContinueShopping);
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_PLAYING;
+ } else {
+ if (ActorCutscene_GetCurrentIndex() == 0x7C) {
+ ActorCutscene_Stop(0x7C);
+ }
+ this->cutscene = this->lookToShopkeeperCutscene;
+ ActorCutscene_SetIntentToPlay(this->cutscene);
+ }
+ }
+ if (func_800B84D0(&this->actor, globalCtx)) {
+ func_80151938(globalCtx, 0x642);
+ } else {
+ func_800B85E0(&this->actor, globalCtx, 400.0f, -1);
+ }
+}
+
+void EnOssan_PositionSelectedItem(EnOssan* this) {
+ static Vec3f sSelectedItemPosition[] = {
+ { 35.0f, 68.0f, -130.0f },
+ { -35.0f, 68.0f, -130.0f },
+ };
+ EnGirlA* item;
+ u8 i = this->cursorIdx;
+ u8 i2;
+ ShopItem* shopItem = &sShops[this->actor.params][i];
+ Vec3f worldPos;
+
+ item = this->items[i];
+ i2 = i >> 2;
+ VEC3F_LERPIMPDST(&worldPos, &shopItem->spawnPos, &sSelectedItemPosition[i2], this->shopItemSelectedTween);
+
+ item->actor.world.pos.x = worldPos.x;
+ item->actor.world.pos.y = worldPos.y;
+ item->actor.world.pos.z = worldPos.z;
+}
+
+void EnOssan_ResetItemPosition(EnOssan* this) {
+ this->shopItemSelectedTween = 0.0f;
+ EnOssan_PositionSelectedItem(this);
+}
+
+/*
+ * Returns true if animation has completed
+ */
+s32 EnOssan_TakeItemOffShelf(EnOssan* this) {
+ Math_ApproachF(&this->shopItemSelectedTween, 1.0f, 1.0f, 0.15f);
+ if (this->shopItemSelectedTween >= 0.85f) {
+ this->shopItemSelectedTween = 1.0f;
+ }
+ EnOssan_PositionSelectedItem(this);
+ if (this->shopItemSelectedTween == 1.0f) {
+ return true;
+ }
+ return false;
+}
+
+/*
+ * Returns true if animation has completed
+ */
+s32 EnOssan_ReturnItemToShelf(EnOssan* this) {
+ Math_ApproachF(&this->shopItemSelectedTween, 0.0f, 1.0f, 0.15f);
+ if (this->shopItemSelectedTween <= 0.15f) {
+ this->shopItemSelectedTween = 0.0f;
+ }
+ EnOssan_PositionSelectedItem(this);
+ if (this->shopItemSelectedTween == 0.0f) {
+ return true;
+ }
+ return false;
+}
+
+void EnOssan_UpdateItemSelectedProperty(EnOssan* this) {
+ EnGirlA** items = this->items;
+ EnGirlA* item;
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(this->items); i++, items++) {
+ item = *items;
+ if (item != NULL) {
+ if (this->actionFunc != EnOssan_SelectItem && this->actionFunc != EnOssan_CannotBuy &&
+ this->drawCursor == 0) {
+ item->isSelected = false;
+ } else {
+ item->isSelected = this->cursorIdx == i ? true : false;
+ }
+ }
+ }
+}
+
+void EnOssan_UpdateCursorAnim(EnOssan* this) {
+ f32 t = this->cursorAnimTween;
+
+ if (this->cursorAnimState == 0) {
+ t += 0.05f;
+ if (t >= 1.0f) {
+ t = 1.0f;
+ this->cursorAnimState = 1;
+ }
+ } else {
+ t -= 0.05f;
+ if (t <= 0.0f) {
+ t = 0.0f;
+ this->cursorAnimState = 0;
+ }
+ }
+ this->cursorColorR = COL_CHAN_MIX(0, 0.0f, t);
+ this->cursorColorG = COL_CHAN_MIX(80, 80.0f, t);
+ this->cursorColorB = COL_CHAN_MIX(255, 0.0f, t);
+ this->cursorColorA = COL_CHAN_MIX(255, 0.0f, t);
+ this->cursorAnimTween = t;
+}
+
+void EnOssan_UpdateStickDirectionPromptAnim(EnOssan* this) {
+ f32 arrowAnimTween = this->arrowAnimTween;
+ f32 stickAnimTween = this->stickAnimTween;
+
+ // Possibly Fake
+ s32 maxColor = 255;
+ f32 tmp;
+
+ if (this->arrowAnimState == 0) {
+ arrowAnimTween += 0.05f;
+ if (arrowAnimTween > 1.0f) {
+ arrowAnimTween = 1.0f;
+ this->arrowAnimState = 1;
+ }
+ } else {
+ arrowAnimTween -= 0.05f;
+ if (arrowAnimTween < 0.0f) {
+ arrowAnimTween = 0.0f;
+ this->arrowAnimState = 0;
+ }
+ }
+ this->arrowAnimTween = arrowAnimTween;
+
+ if (this->stickAnimState == 0) {
+ stickAnimTween += 0.1f;
+ if (stickAnimTween > 1.0f) {
+ stickAnimTween = 1.0f;
+ this->stickAnimState = 1;
+ }
+ } else {
+ stickAnimTween = 0.0f;
+ this->stickAnimState = 0;
+ }
+
+ tmp = 155.0f * arrowAnimTween;
+
+ this->stickAnimTween = stickAnimTween;
+
+ this->stickLeftPrompt.arrowColorR = COL_CHAN_MIX(255, 155.0f, arrowAnimTween);
+ this->stickLeftPrompt.arrowColorG = COL_CHAN_MIX(maxColor, 155.0f, arrowAnimTween);
+ this->stickLeftPrompt.arrowColorB = COL_CHAN_MIX(0, -100, arrowAnimTween);
+ this->stickLeftPrompt.arrowColorA = COL_CHAN_MIX(200, 50.0f, arrowAnimTween);
+
+ this->stickRightPrompt.arrowColorR = (maxColor - ((s32)tmp)) & 0xFF;
+ this->stickRightPrompt.arrowColorG = (255 - ((s32)tmp)) & 0xFF;
+ this->stickRightPrompt.arrowColorB = COL_CHAN_MIX(0, -100.0f, arrowAnimTween);
+ this->stickRightPrompt.arrowColorA = COL_CHAN_MIX(200, 50.0f, arrowAnimTween);
+
+ this->stickRightPrompt.arrowTexX = 290.0f;
+ this->stickLeftPrompt.arrowTexX = 33.0f;
+
+ this->stickRightPrompt.stickTexX = 274.0f;
+ this->stickRightPrompt.stickTexX += 8.0f * stickAnimTween;
+ this->stickLeftPrompt.stickTexX = 49.0f;
+ this->stickLeftPrompt.stickTexX -= 8.0f * stickAnimTween;
+
+ this->stickLeftPrompt.arrowTexY = this->stickRightPrompt.arrowTexY = 91.0f;
+ this->stickLeftPrompt.stickTexY = this->stickRightPrompt.stickTexY = 95.0f;
+}
+
+void EnOssan_WaitForBlink(EnOssan* this) {
+ s16 decr = this->blinkTimer - 1;
+
+ if (decr != 0) {
+ this->blinkTimer = decr;
+ } else {
+ this->blinkFunc = EnOssan_Blink;
+ }
+}
+
+void EnOssan_Blink(EnOssan* this) {
+ s16 decr = this->blinkTimer - 1;
+ s16 eyeTexIndexTemp;
+
+ if (decr != 0) {
+ this->blinkTimer = decr;
+ return;
+ }
+ eyeTexIndexTemp = this->eyeTexIndex + 1;
+ if (eyeTexIndexTemp > 2) {
+ this->eyeTexIndex = 0;
+ this->blinkTimer = (s32)(Rand_ZeroOne() * 60.0f) + 20;
+ this->blinkFunc = EnOssan_WaitForBlink;
+ } else {
+ this->eyeTexIndex = eyeTexIndexTemp;
+ this->blinkTimer = 1;
+ }
+}
+
+void EnOssan_InitCuriosityShopMan(EnOssan* this, GlobalContext* globalCtx) {
+ SkelAnime_InitSV(globalCtx, &this->skelAnime, &D_06013320, &D_06012C34, this->limbDrawTbl, this->transitionDrawTbl,
+ 19);
+ this->actor.draw = EnOssan_DrawCuriosityShopMan;
+}
+
+void EnOssan_InitPartTimeWorker(EnOssan* this, GlobalContext* globalCtx) {
+ SkelAnime_InitSV(globalCtx, &this->skelAnime, &D_060028A0, &D_06009D34, this->limbDrawTbl, this->transitionDrawTbl,
+ 16);
+ this->actor.draw = EnOssan_DrawPartTimeWorker;
+}
+
+s32 EnOssan_GetWelcomeCuriosityShopMan(EnOssan* this, GlobalContext* globalCtx) {
+ Player* player = PLAYER;
+ u16 ret = func_800F1250(globalCtx, 0x2F);
+
+ if (ret != 0) {
+ this->animationIdx = 4;
+ this->flags |= END_INTERACTION;
+ return ret;
+ }
+ switch (player->transformation) {
+ case PLAYER_FORM_DEKU:
+ this->animationIdx = 10;
+ if (gSaveContext.weekEventReg[0x12] & 0x10) {
+ return sWelcomeDekuTextIds[ENOSSAN_CURIOSITY_SHOP_MAN];
+ }
+ return sWelcomeDekuFirstTimeTextIds[ENOSSAN_CURIOSITY_SHOP_MAN];
+ case PLAYER_FORM_ZORA:
+ this->animationIdx = 8;
+ if (gSaveContext.weekEventReg[0x12] & 8) {
+ return sWelcomeZoraTextIds[ENOSSAN_CURIOSITY_SHOP_MAN];
+ }
+ return sWelcomeZoraFirstTimeTextIds[ENOSSAN_CURIOSITY_SHOP_MAN];
+ case PLAYER_FORM_GORON:
+ this->animationIdx = 6;
+ if (gSaveContext.weekEventReg[0x12] & 4) {
+ return sWelcomeGoronTextIds[ENOSSAN_CURIOSITY_SHOP_MAN];
+ }
+ return sWelcomeGoronFirstTimeTextIds[ENOSSAN_CURIOSITY_SHOP_MAN];
+ }
+ this->animationIdx = 4;
+ return sWelcomeHumanTextIds[ENOSSAN_CURIOSITY_SHOP_MAN];
+}
+
+s32 EnOssan_GetWelcomePartTimeWorker(EnOssan* this, GlobalContext* globalCtx) {
+ Player* player = PLAYER;
+ u16 ret = func_800F1250(globalCtx, 0x36);
+
+ if (ret != 0) {
+ this->flags |= END_INTERACTION;
+ return ret;
+ }
+ switch (player->transformation) {
+ case PLAYER_FORM_DEKU:
+ if (gSaveContext.weekEventReg[0x37] & 0x10) {
+ return sWelcomeDekuTextIds[ENOSSAN_PART_TIME_WORKER];
+ }
+ return sWelcomeDekuFirstTimeTextIds[ENOSSAN_PART_TIME_WORKER];
+ case PLAYER_FORM_ZORA:
+ if (gSaveContext.weekEventReg[0x37] & 8) {
+ return sWelcomeZoraTextIds[ENOSSAN_PART_TIME_WORKER];
+ }
+ return sWelcomeZoraFirstTimeTextIds[ENOSSAN_PART_TIME_WORKER];
+ case PLAYER_FORM_GORON:
+ if (gSaveContext.weekEventReg[0x37] & 4) {
+ return sWelcomeGoronTextIds[ENOSSAN_PART_TIME_WORKER];
+ }
+ return sWelcomeGoronFirstTimeTextIds[ENOSSAN_PART_TIME_WORKER];
+ }
+ return sWelcomeHumanTextIds[ENOSSAN_PART_TIME_WORKER];
+}
+
+void EnOssan_SetHaveMet(EnOssan* this) {
+ switch (this->textId) {
+ case 0x06A9:
+ gSaveContext.weekEventReg[0x12] |= 0x10;
+ break;
+ case 0x06C6:
+ gSaveContext.weekEventReg[0x37] |= 0x10;
+ break;
+ case 0x06A7:
+ gSaveContext.weekEventReg[0x12] |= 8;
+ break;
+ case 0x06C4:
+ gSaveContext.weekEventReg[0x37] |= 8;
+ break;
+ case 0x06A5:
+ gSaveContext.weekEventReg[0x12] |= 4;
+ break;
+ case 0x06C2:
+ gSaveContext.weekEventReg[0x37] |= 4;
+ break;
+ }
+}
+
+void EnOssan_InitShop(EnOssan* this, GlobalContext* globalCtx) {
+ static EnOssanActionFunc sInitFuncs[] = { EnOssan_InitCuriosityShopMan, EnOssan_InitPartTimeWorker };
+ ShopItem* shopItems;
+
+ if (Object_IsLoaded(&globalCtx->objectCtx, this->objIndex)) {
+ this->actor.flags &= ~0x10;
+ this->actor.objBankIndex = this->objIndex;
+ Actor_SetObjectSegment(globalCtx, &this->actor);
+ shopItems = sShops[this->actor.params];
+ ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 20.0f);
+ sInitFuncs[this->actor.params](this, globalCtx);
+ this->textId = sWelcomeHumanTextIds[this->actor.params];
+ EnOssan_GetCutscenes(this, globalCtx);
+
+ this->cursorY = this->cursorX = 100.0f;
+ this->cutsceneState = ENOSSAN_CUTSCENESTATE_STOPPED;
+ this->cutscene = this->lookToShopkeeperCutscene;
+ this->actor.colChkInfo.mass = MASS_IMMOVABLE;
+ this->actor.colChkInfo.cylRadius = 50;
+ this->stickAccumX = this->stickAccumY = 0;
+
+ this->cursorIdx = 0;
+ this->cursorZ = 1.5f;
+ this->cursorColorR = 0;
+ this->cursorColorG = 80;
+ this->cursorColorB = 255;
+ this->cursorColorA = 255;
+ this->cursorAnimTween = 0.0f;
+ this->cursorAnimState = 0;
+ this->drawCursor = 0;
+
+ this->stickLeftPrompt.stickColorR = 200;
+ this->stickLeftPrompt.stickColorG = 200;
+ this->stickLeftPrompt.stickColorB = 200;
+ this->stickLeftPrompt.stickColorA = 180;
+ this->stickLeftPrompt.stickTexX = 49.0f;
+ this->stickLeftPrompt.stickTexY = 95.0f;
+ this->stickLeftPrompt.arrowColorR = 255;
+ this->stickLeftPrompt.arrowColorG = 255;
+ this->stickLeftPrompt.arrowColorB = 0;
+ this->stickLeftPrompt.arrowColorA = 200;
+ this->stickLeftPrompt.arrowTexX = 33.0f;
+ this->stickLeftPrompt.arrowTexY = 91.0f;
+ this->stickLeftPrompt.texZ = 1.0f;
+ this->stickLeftPrompt.isEnabled = false;
+
+ this->stickRightPrompt.stickColorR = 200;
+ this->stickRightPrompt.stickColorG = 200;
+ this->stickRightPrompt.stickColorB = 200;
+ this->stickRightPrompt.stickColorA = 180;
+ this->stickRightPrompt.stickTexX = 274.0f;
+ this->stickRightPrompt.stickTexY = 95.0f;
+ this->stickRightPrompt.arrowColorR = 255;
+ this->stickRightPrompt.arrowColorG = 255;
+ this->stickRightPrompt.arrowColorB = 0;
+ this->stickRightPrompt.arrowColorA = 200;
+ this->stickRightPrompt.arrowTexX = 290.0f;
+ this->stickRightPrompt.arrowTexY = 91.0f;
+ this->stickRightPrompt.texZ = 1.0f;
+ this->stickRightPrompt.isEnabled = false;
+
+ this->arrowAnimState = 0;
+ this->stickAnimState = 0;
+ this->arrowAnimTween = 0.0f;
+ this->stickAnimTween = 0.0f;
+ this->shopItemSelectedTween = 0.0f;
+ Actor_SetScale(&this->actor, sActorScales[this->actor.params]);
+ this->animationIdx = 1;
+ func_8013BC6C(&this->skelAnime, sAnimations[this->actor.params], 1);
+ EnOssan_SpawnShopItems(this, globalCtx, shopItems);
+ this->blinkTimer = 20;
+ this->eyeTexIndex = 0;
+ this->blinkFunc = EnOssan_WaitForBlink;
+ this->actor.flags &= ~1;
+ EnOssan_SetupAction(this, EnOssan_Idle);
+ }
+}
+
+void EnOssan_GetCutscenes(EnOssan* this, GlobalContext* globalCtx) {
+ this->lookToShopkeeperCutscene = this->actor.cutscene;
+ this->lookToLeftShelfCutscene = ActorCutscene_GetAdditionalCutscene(this->lookToShopkeeperCutscene);
+ this->lookToRightShelfCutscene = ActorCutscene_GetAdditionalCutscene(this->lookToLeftShelfCutscene);
+ this->lookToShopKeeperFromShelfCutscene = ActorCutscene_GetAdditionalCutscene(this->lookToRightShelfCutscene);
+}
+
+void EnOssan_Update(Actor* thisx, GlobalContext* globalCtx) {
+ EnOssan* this = THIS;
+
+ if (this->actionFunc != EnOssan_InitShop) {
+ this->blinkFunc(this);
+ EnOssan_UpdateJoystickInputState(globalCtx, this);
+ EnOssan_UpdateItemSelectedProperty(this);
+ EnOssan_UpdateStickDirectionPromptAnim(this);
+ EnOssan_UpdateCursorAnim(this);
+ func_800E9250(globalCtx, &this->actor, &this->headRot, &this->unk2CC, this->actor.focus.pos);
+ this->actionFunc(this, globalCtx);
+ Actor_SetHeight(&this->actor, 90.0f);
+ SkelAnime_FrameUpdateMatrix(&this->skelAnime);
+ } else {
+ this->actionFunc(this, globalCtx);
+ }
+}
+
+void EnOssan_DrawCursor(GlobalContext* globalCtx, EnOssan* this, f32 x, f32 y, f32 z, u8 drawCursor) {
+ s32 ulx, uly, lrx, lry;
+ f32 w;
+ s32 dsdx;
+
+ ((void)"../z_en_oB1.c"); // Unreferenced
+
+ OPEN_DISPS(globalCtx->state.gfxCtx);
+ if (drawCursor != 0) {
+ func_8012C654(globalCtx->state.gfxCtx);
+ gDPSetPrimColor(OVERLAY_DISP++, 0, 0, this->cursorColorR, this->cursorColorG, this->cursorColorB,
+ this->cursorColorA);
+ gDPLoadTextureBlock_4b(OVERLAY_DISP++, &D_0401F740, G_IM_FMT_IA, 16, 16, 0, G_TX_MIRROR | G_TX_WRAP,
+ G_TX_MIRROR | G_TX_WRAP, 4, 4, G_TX_NOLOD, G_TX_NOLOD);
+ w = 16.0f * z;
+ ulx = (x - w) * 4.0f;
+ uly = (y - w) * 4.0f;
+ lrx = (x + w) * 4.0f;
+ lry = (y + w) * 4.0f;
+ dsdx = (1.0f / z) * 1024.0f;
+ gSPTextureRectangle(OVERLAY_DISP++, ulx, uly, lrx, lry, G_TX_RENDERTILE, 0, 0, dsdx, dsdx);
+ }
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
+}
+
+void EnOssan_DrawTextRec(GlobalContext* globalCtx, s32 r, s32 g, s32 b, s32 a, f32 x, f32 y, f32 z, s32 s, s32 t,
+ f32 dx, f32 dy) {
+ f32 unk;
+ s32 ulx, uly, lrx, lry;
+ f32 w, h;
+ s32 dsdx, dtdy;
+
+ ((void)"../z_en_oB1.c"); // Unreferenced
+
+ OPEN_DISPS(globalCtx->state.gfxCtx);
+ gDPPipeSync(OVERLAY_DISP++);
+ gDPSetPrimColor(OVERLAY_DISP++, 0, 0, r, g, b, a);
+
+ w = 8.0f * z;
+ ulx = (x - w) * 4.0f;
+ lrx = (x + w) * 4.0f;
+
+ h = 12.0f * z;
+ uly = (y - h) * 4.0f;
+ lry = (y + h) * 4.0f;
+
+ unk = 1024 * (1.0f / z);
+ dsdx = unk * dx;
+ dtdy = dy * unk;
+
+ gSPTextureRectangle(OVERLAY_DISP++, ulx, uly, lrx, lry, G_TX_RENDERTILE, s, t, dsdx, dtdy);
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
+}
+
+void EnOssan_DrawStickDirectionPrompts(GlobalContext* globalCtx, EnOssan* this) {
+ s32 drawStickRightPrompt = this->stickLeftPrompt.isEnabled;
+ s32 drawStickLeftPrompt = this->stickRightPrompt.isEnabled;
+
+ ((void)"../z_en_oB1.c"); // Unreferenced
+
+ OPEN_DISPS(globalCtx->state.gfxCtx);
+ if (drawStickRightPrompt || drawStickLeftPrompt) {
+ func_8012C654(globalCtx->state.gfxCtx);
+ gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetTextureImage(OVERLAY_DISP++, G_IM_FMT_IA, G_IM_SIZ_16b, 1, &D_0401F8C0);
+ gDPSetTile(OVERLAY_DISP++, G_IM_FMT_IA, G_IM_SIZ_16b, 0, 0x0000, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOLOD);
+ gDPLoadSync(OVERLAY_DISP++);
+ gDPLoadBlock(OVERLAY_DISP++, G_TX_LOADTILE, 0, 0, 191, 1024);
+ gDPPipeSync(OVERLAY_DISP++);
+ gDPSetTile(OVERLAY_DISP++, G_IM_FMT_IA, G_IM_SIZ_8b, 2, 0x0000, G_TX_RENDERTILE, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOLOD);
+ gDPSetTileSize(OVERLAY_DISP++, G_TX_RENDERTILE, 0, 0, 15 * 4, 23 * 4);
+ if (drawStickRightPrompt) {
+ EnOssan_DrawTextRec(globalCtx, this->stickLeftPrompt.arrowColorR, this->stickLeftPrompt.arrowColorG,
+ this->stickLeftPrompt.arrowColorB, this->stickLeftPrompt.arrowColorA,
+ this->stickLeftPrompt.arrowTexX, this->stickLeftPrompt.arrowTexY,
+ this->stickLeftPrompt.texZ, 0, 0, -1.0f, 1.0f);
+ }
+ if (drawStickLeftPrompt) {
+ EnOssan_DrawTextRec(globalCtx, this->stickRightPrompt.arrowColorR, this->stickRightPrompt.arrowColorG,
+ this->stickRightPrompt.arrowColorB, this->stickRightPrompt.arrowColorA,
+ this->stickRightPrompt.arrowTexX, this->stickRightPrompt.arrowTexY,
+ this->stickRightPrompt.texZ, 0, 0, 1.0f, 1.0f);
+ }
+ gDPSetTextureImage(OVERLAY_DISP++, G_IM_FMT_IA, G_IM_SIZ_16b, 1, &D_0401F7C0);
+ gDPSetTile(OVERLAY_DISP++, G_IM_FMT_IA, G_IM_SIZ_16b, 0, 0x0000, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOLOD);
+ gDPLoadSync(OVERLAY_DISP++);
+ gDPLoadBlock(OVERLAY_DISP++, G_TX_LOADTILE, 0, 0, 127, 1024);
+ gDPPipeSync(OVERLAY_DISP++);
+ gDPSetTile(OVERLAY_DISP++, G_IM_FMT_IA, G_IM_SIZ_8b, 2, 0x0000, G_TX_RENDERTILE, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOLOD);
+ gDPSetTileSize(OVERLAY_DISP++, G_TX_RENDERTILE, 0, 0, 15 * 4, 15 * 4);
+ if (drawStickRightPrompt) {
+ EnOssan_DrawTextRec(globalCtx, this->stickLeftPrompt.stickColorR, this->stickLeftPrompt.stickColorG,
+ this->stickLeftPrompt.stickColorB, this->stickLeftPrompt.stickColorA,
+ this->stickLeftPrompt.stickTexX, this->stickLeftPrompt.stickTexY,
+ this->stickLeftPrompt.texZ, 0, 0, -1.0f, 1.0f);
+ }
+ if (drawStickLeftPrompt) {
+ EnOssan_DrawTextRec(globalCtx, this->stickRightPrompt.stickColorR, this->stickRightPrompt.stickColorG,
+ this->stickRightPrompt.stickColorB, this->stickRightPrompt.stickColorA,
+ this->stickRightPrompt.stickTexX, this->stickRightPrompt.stickTexY,
+ this->stickRightPrompt.texZ, 0, 0, 1.0f, 1.0f);
+ }
+ }
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
+}
+
+s32 EnOssan_OverrideLimbDrawCuriosityShopMan(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos,
+ Vec3s* rot, Actor* thisx) {
+ EnOssan* this = THIS;
+
+ if (limbIndex == 16) {
+ SysMatrix_InsertXRotation_s(this->headRot.y, MTXMODE_APPLY);
+ }
+ return false;
+}
+
+s32 EnOssan_OverrideLimbDrawPartTimeWorker(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
+ Actor* thisx) {
+ EnOssan* this = THIS;
+
+ if (limbIndex == 15) {
+ SysMatrix_InsertXRotation_s(this->headRotPartTimeWorker.y, MTXMODE_APPLY);
+ SysMatrix_InsertZRotation_s(this->headRotPartTimeWorker.x, MTXMODE_APPLY);
+ }
+ return false;
+}
+
+void EnOssan_PostLimbDrawCuriosityShopMan(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot,
+ Actor* thisx) {
+ EnOssan* this = THIS;
+
+ if (limbIndex == 1 || limbIndex == 9 || limbIndex == 12) {
+ rot->y += (s16)Math_SinS(this->limbRotTableY[limbIndex]) * 200;
+ rot->z += (s16)Math_CosS(this->limbRotTableZ[limbIndex]) * 200;
+ }
+}
+
+void EnOssan_PostLimbDrawPartTimeWorker(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot,
+ Actor* thisx) {
+ static Vec3f sPartTimeWorkerFocusOffset = { 800.0f, 500.0f, 0.0f };
+ EnOssan* this = THIS;
+
+ if (limbIndex == 15) {
+ SysMatrix_MultiplyVector3fByState(&sPartTimeWorkerFocusOffset, &this->actor.focus.pos);
+ }
+}
+
+void EnOssan_DrawCuriosityShopMan(Actor* thisx, GlobalContext* globalCtx) {
+ static TexturePtr sEyeTextures[] = { &D_06005BC0, &D_06006D40, &D_06007140 };
+ EnOssan* this = THIS;
+ s32 pad;
+
+ OPEN_DISPS(globalCtx->state.gfxCtx);
+ func_8012C28C(globalCtx->state.gfxCtx);
+ gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTexIndex]));
+ SkelAnime_DrawSV(globalCtx, this->skelAnime.skeleton, this->skelAnime.limbDrawTbl, this->skelAnime.dListCount,
+ EnOssan_OverrideLimbDrawCuriosityShopMan, EnOssan_PostLimbDrawCuriosityShopMan, &this->actor);
+ EnOssan_DrawCursor(globalCtx, this, this->cursorX, this->cursorY, this->cursorZ, this->drawCursor);
+ EnOssan_DrawStickDirectionPrompts(globalCtx, this);
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
+}
+
+void EnOssan_DrawPartTimeWorker(Actor* thisx, GlobalContext* globalCtx) {
+ static TexturePtr sEyeTextures[] = { &D_06006498, &D_06006B18, &D_06006F18 };
+ EnOssan* this = THIS;
+ s32 pad;
+
+ OPEN_DISPS(globalCtx->state.gfxCtx);
+ func_8012C28C(globalCtx->state.gfxCtx);
+ gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTexIndex]));
+ SkelAnime_DrawSV(globalCtx, this->skelAnime.skeleton, this->skelAnime.limbDrawTbl, this->skelAnime.dListCount,
+ EnOssan_OverrideLimbDrawPartTimeWorker, EnOssan_PostLimbDrawPartTimeWorker, &this->actor);
+ EnOssan_DrawCursor(globalCtx, this, this->cursorX, this->cursorY, this->cursorZ, this->drawCursor);
+ EnOssan_DrawStickDirectionPrompts(globalCtx, this);
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
+}
diff --git a/src/overlays/actors/ovl_En_Ossan/z_en_ossan.h b/src/overlays/actors/ovl_En_Ossan/z_en_ossan.h
index 12c844674..693c7d2ca 100644
--- a/src/overlays/actors/ovl_En_Ossan/z_en_ossan.h
+++ b/src/overlays/actors/ovl_En_Ossan/z_en_ossan.h
@@ -3,13 +3,82 @@
#include <global.h>
+#include "overlays/actors/ovl_En_GirlA/z_en_girla.h"
+
struct EnOssan;
+typedef void (*EnOssanActionFunc)(struct EnOssan*, GlobalContext*);
+typedef void (*EnOssanBlinkFunc)(struct EnOssan*);
+
typedef struct EnOssan {
/* 0x000 */ Actor actor;
- /* 0x144 */ char unk_144[0x2C8];
+ /* 0x144 */ SkelAnime skelAnime;
+ /* 0x188 */ EnOssanActionFunc actionFunc;
+ /* 0x18C */ EnOssanActionFunc tmpActionFunc; // Used to restore back to correct browsing function
+ /* 0x190 */ ColliderCylinder collider;
+ /* 0x1DC */ s16 delayTimer;
+ /* 0x1DE */ s8 objIndex;
+ /* 0x1E0 */ s16 eyeTexIndex;
+ /* 0x1E2 */ s16 blinkTimer;
+ /* 0x1E4 */ EnOssanBlinkFunc blinkFunc;
+ /* 0x1E8 */ EnGirlA* items[8];
+ /* 0x208 */ s32 stickAccumX;
+ /* 0x20C */ s32 stickAccumY;
+ /* 0x210 */ u8 moveHorizontal;
+ /* 0x211 */ u8 moveVertical;
+ /* 0x214 */ f32 cursorX;
+ /* 0x218 */ f32 cursorY;
+ /* 0x21C */ f32 cursorZ;
+ /* 0x220 */ u32 cursorColorR;
+ /* 0x224 */ u32 cursorColorG;
+ /* 0x228 */ u32 cursorColorB;
+ /* 0x22C */ u32 cursorColorA;
+ /* 0x230 */ f32 cursorAnimTween;
+ /* 0x234 */ u8 cursorAnimState;
+ /* 0x235 */ u8 drawCursor;
+ /* 0x236 */ u8 cursorIdx;
+ /* 0x238 */ StickDirectionPrompt stickLeftPrompt;
+ /* 0x270 */ StickDirectionPrompt stickRightPrompt;
+ /* 0x2A8 */ f32 arrowAnimTween;
+ /* 0x2AC */ f32 stickAnimTween;
+ /* 0x2B0 */ u8 arrowAnimState;
+ /* 0x2B1 */ u8 stickAnimState;
+ /* 0x2B4 */ f32 shopItemSelectedTween;
+ /* 0x2B8 */ s16 lookToShopkeeperCutscene;
+ /* 0x2BA */ s16 lookToLeftShelfCutscene;
+ /* 0x2BC */ s16 lookToRightShelfCutscene;
+ /* 0x2BE */ s16 lookToShopKeeperFromShelfCutscene;
+ /* 0x2C0 */ s16 cutscene;
+ /* 0x2C2 */ s16 cutsceneState;
+ /* 0x2C4 */ u16 textId;
+ /* 0x2C6 */ Vec3s headRot;
+ /* 0x2CC */ Vec3s unk2CC; // Set but never used
+ /* 0x2D2 */ s16 limbRotTableY[19];
+ /* 0x2F8 */ s16 limbRotTableZ[19];
+ /* 0x31E */ Vec3s limbDrawTbl[19];
+ /* 0x390 */ Vec3s transitionDrawTbl[19];
+ /* 0x402 */ s16 animationIdx;
+ /* 0x404 */ Vec3s headRotPartTimeWorker;
+ /* 0x40A */ u16 flags;
} EnOssan; // size = 0x40C
+/* Note:
+* Items on shelves are indexed as:
+* 7 5 3 1
+* 6 4 2 0
+*/
+
+typedef enum {
+ /* 0 */ ENOSSAN_CURIOSITY_SHOP_MAN,
+ /* 1 */ ENOSSAN_PART_TIME_WORKER
+} EnOssanWorker;
+
+typedef enum {
+ /* 0 */ ENOSSAN_CUTSCENESTATE_STOPPED,
+ /* 1 */ ENOSSAN_CUTSCENESTATE_WAITING,
+ /* 2 */ ENOSSAN_CUTSCENESTATE_PLAYING
+} EnOssanCutsceneState;
+
extern const ActorInit En_Ossan_InitVars;
#endif // Z_EN_OSSAN_H
diff --git a/tables/functions.txt b/tables/functions.txt
index da6a25bcc..917600fdd 100644
--- a/tables/functions.txt
+++ b/tables/functions.txt
@@ -5764,74 +5764,74 @@
0x808A7E30:("EnRiverSound_Init",),
0x808A7EB8:("EnRiverSound_Update",),
0x808A7FD0:("EnRiverSound_Draw",),
- 0x808A80A0:("func_808A80A0",),
- 0x808A80AC:("func_808A80AC",),
- 0x808A812C:("func_808A812C",),
- 0x808A8218:("func_808A8218",),
- 0x808A82F4:("func_808A82F4",),
+ 0x808A80A0:("EnOssan_SetupAction",),
+ 0x808A80AC:("EnOssan_TestItemSelected",),
+ 0x808A812C:("EnOssan_CheckValidSpawn",),
+ 0x808A8218:("EnOssan_RotateHead",),
+ 0x808A82F4:("EnOssan_SpawnShopItems",),
0x808A83BC:("EnOssan_Init",),
0x808A8470:("EnOssan_Destroy",),
- 0x808A849C:("func_808A849C",),
- 0x808A8500:("func_808A8500",),
- 0x808A85FC:("func_808A85FC",),
- 0x808A8644:("func_808A8644",),
- 0x808A86A8:("func_808A86A8",),
- 0x808A8708:("func_808A8708",),
- 0x808A875C:("func_808A875C",),
- 0x808A8798:("func_808A8798",),
- 0x808A890C:("func_808A890C",),
- 0x808A8B74:("func_808A8B74",),
- 0x808A8CC0:("func_808A8CC0",),
- 0x808A8DF8:("func_808A8DF8",),
- 0x808A8E84:("func_808A8E84",),
- 0x808A8EEC:("func_808A8EEC",),
- 0x808A90A4:("func_808A90A4",),
- 0x808A91B4:("func_808A91B4",),
- 0x808A935C:("func_808A935C",),
- 0x808A9400:("func_808A9400",),
- 0x808A94FC:("func_808A94FC",),
- 0x808A95F8:("func_808A95F8",),
- 0x808A980C:("func_808A980C",),
- 0x808A98E4:("func_808A98E4",),
- 0x808A9AB8:("func_808A9AB8",),
- 0x808A9C8C:("func_808A9C8C",),
- 0x808A9D64:("func_808A9D64",),
- 0x808A9E20:("func_808A9E20",),
- 0x808A9E5C:("func_808A9E5C",),
- 0x808A9E98:("func_808A9E98",),
- 0x808AA0C8:("func_808AA0C8",),
- 0x808AA1B0:("func_808AA1B0",),
- 0x808AA224:("func_808AA224",),
- 0x808AA2C8:("func_808AA2C8",),
- 0x808AA33C:("func_808AA33C",),
- 0x808AA404:("func_808AA404",),
- 0x808AA5E8:("func_808AA5E8",),
- 0x808AA6D8:("func_808AA6D8",),
- 0x808AA79C:("func_808AA79C",),
- 0x808AA7C0:("func_808AA7C0",),
- 0x808AA85C:("func_808AA85C",),
- 0x808AA8E8:("func_808AA8E8",),
- 0x808AAA64:("func_808AAA64",),
- 0x808AAB30:("func_808AAB30",),
- 0x808AACE0:("func_808AACE0",),
- 0x808AAD14:("func_808AAD14",),
- 0x808AADB4:("func_808AADB4",),
- 0x808AAE1C:("func_808AAE1C",),
- 0x808AAE84:("func_808AAE84",),
- 0x808AAFB0:("func_808AAFB0",),
- 0x808AB0B0:("func_808AB0B0",),
- 0x808AB16C:("func_808AB16C",),
- 0x808AB404:("func_808AB404",),
+ 0x808A849C:("EnOssan_UpdateCursorPos",),
+ 0x808A8500:("EnOssan_EndInteraction",),
+ 0x808A85FC:("EnOssan_TestEndInteraction",),
+ 0x808A8644:("EnOssan_TestCancelOption",),
+ 0x808A86A8:("EnOssan_SetupStartShopping",),
+ 0x808A8708:("EnOssan_StartShopping",),
+ 0x808A875C:("EnOssan_SetupLookToShopkeeperFromShelf",),
+ 0x808A8798:("EnOssan_Idle",),
+ 0x808A890C:("EnOssan_BeginInteraction",),
+ 0x808A8B74:("EnOssan_UpdateJoystickInputState",),
+ 0x808A8CC0:("EnOssan_SetCursorIndexFromNeutral",),
+ 0x808A8DF8:("EnOssan_CursorRight",),
+ 0x808A8E84:("EnOssan_CursorLeft",),
+ 0x808A8EEC:("EnOssan_Hello",),
+ 0x808A90A4:("EnOssan_FacingShopkeeperDialogResult",),
+ 0x808A91B4:("EnOssan_FaceShopkeeper",),
+ 0x808A935C:("EnOssan_TalkToShopkeeper",),
+ 0x808A9400:("EnOssan_LookToLeftShelf",),
+ 0x808A94FC:("EnOssan_LookToRightShelf",),
+ 0x808A95F8:("EnOssan_CursorUpDown",),
+ 0x808A980C:("EnOssan_HasPlayerSelectedItem",),
+ 0x808A98E4:("EnOssan_BrowseLeftShelf",),
+ 0x808A9AB8:("EnOssan_BrowseRightShelf",),
+ 0x808A9C8C:("EnOssan_LookToShopkeeperFromShelf",),
+ 0x808A9D64:("EnOssan_SetupBuyItemWithFanfare",),
+ 0x808A9E20:("EnOssan_SetupCannotBuy",),
+ 0x808A9E5C:("EnOssan_SetupBuy",),
+ 0x808A9E98:("EnOssan_HandleCanBuyItem",),
+ 0x808AA0C8:("EnOssan_SelectItem",),
+ 0x808AA1B0:("EnOssan_CannotBuy",),
+ 0x808AA224:("EnOssan_CanBuy",),
+ 0x808AA2C8:("EnOssan_BuyItemWithFanfare",),
+ 0x808AA33C:("EnOssan_SetupItemPurchased",),
+ 0x808AA404:("EnOssan_ContinueShopping",),
+ 0x808AA5E8:("EnOssan_ItemPurchased",),
+ 0x808AA6D8:("EnOssan_PositionSelectedItem",),
+ 0x808AA79C:("EnOssan_ResetItemPosition",),
+ 0x808AA7C0:("EnOssan_TakeItemOffShelf",),
+ 0x808AA85C:("EnOssan_ReturnItemToShelf",),
+ 0x808AA8E8:("EnOssan_UpdateItemSelectedProperty",),
+ 0x808AAA64:("EnOssan_UpdateCursorAnim",),
+ 0x808AAB30:("EnOssan_UpdateStickDirectionPromptAnim",),
+ 0x808AACE0:("EnOssan_WaitForBlink",),
+ 0x808AAD14:("EnOssan_Blink",),
+ 0x808AADB4:("EnOssan_InitCuriosityShopMan",),
+ 0x808AAE1C:("EnOssan_InitPartTimeWorker",),
+ 0x808AAE84:("EnOssan_GetWelcomeCuriosityShopMan",),
+ 0x808AAFB0:("EnOssan_GetWelcomePartTimeWorker",),
+ 0x808AB0B0:("EnOssan_SetHaveMet",),
+ 0x808AB16C:("EnOssan_InitShop",),
+ 0x808AB404:("EnOssan_GetCutscenes",),
0x808AB458:("EnOssan_Update",),
- 0x808AB52C:("func_808AB52C",),
- 0x808AB78C:("func_808AB78C",),
- 0x808AB928:("func_808AB928",),
- 0x808ABCD0:("func_808ABCD0",),
- 0x808ABD10:("func_808ABD10",),
- 0x808ABD60:("func_808ABD60",),
- 0x808ABE18:("func_808ABE18",),
- 0x808ABE58:("func_808ABE58",),
- 0x808ABF30:("func_808ABF30",),
+ 0x808AB52C:("EnOssan_DrawCursor",),
+ 0x808AB78C:("EnOssan_DrawTextRec",),
+ 0x808AB928:("EnOssan_DrawStickDirectionPrompts",),
+ 0x808ABCD0:("EnOssan_OverrideLimbDrawCuriosityShopMan",),
+ 0x808ABD10:("EnOssan_OverrideLimbDrawPartTimeWorker",),
+ 0x808ABD60:("EnOssan_PostLimbDrawCuriosityShopMan",),
+ 0x808ABE18:("EnOssan_PostLimbDrawPartTimeWorker",),
+ 0x808ABE58:("EnOssan_DrawCuriosityShopMan",),
+ 0x808ABF30:("EnOssan_DrawPartTimeWorker",),
0x808AC920:("EnFamos_Init",),
0x808ACB08:("EnFamos_Destroy",),
0x808ACB58:("func_808ACB58",),
diff --git a/tables/variables.txt b/tables/variables.txt
index 2ab696c2d..76867c62d 100644
--- a/tables/variables.txt
+++ b/tables/variables.txt
@@ -6748,41 +6748,33 @@
0x808A8084:("enRiverSoundOverlayRelocations","u32","[5]",0x14),
0x808A809C:("enRiverSoundOverlayInfoOffset","u32","",0x4),
0x808AC010:("En_Ossan_InitVars","UNK_TYPE1","",0x1),
- 0x808AC030:("D_808AC030","UNK_TYPE1","",0x1),
- 0x808AC100:("D_808AC100","UNK_TYPE1","",0x1),
- 0x808AC1C0:("D_808AC1C0","UNK_TYPE1","",0x1),
- 0x808AC1C4:("D_808AC1C4","UNK_TYPE1","",0x1),
- 0x808AC1CC:("D_808AC1CC","UNK_TYPE1","",0x1),
- 0x808AC1D4:("D_808AC1D4","UNK_TYPE1","",0x1),
- 0x808AC254:("D_808AC254","UNK_TYPE2","",0x2),
- 0x808AC256:("D_808AC256","UNK_TYPE2","",0x2),
- 0x808AC258:("D_808AC258","UNK_TYPE1","",0x1),
- 0x808AC25C:("D_808AC25C","UNK_TYPE2","",0x2),
- 0x808AC25E:("D_808AC25E","UNK_TYPE2","",0x2),
- 0x808AC260:("D_808AC260","UNK_TYPE2","",0x2),
- 0x808AC262:("D_808AC262","UNK_TYPE2","",0x2),
- 0x808AC264:("D_808AC264","UNK_TYPE2","",0x2),
- 0x808AC266:("D_808AC266","UNK_TYPE2","",0x2),
- 0x808AC268:("D_808AC268","UNK_TYPE2","",0x2),
- 0x808AC26A:("D_808AC26A","UNK_TYPE2","",0x2),
- 0x808AC26C:("D_808AC26C","UNK_TYPE2","",0x2),
- 0x808AC26E:("D_808AC26E","UNK_TYPE2","",0x2),
- 0x808AC270:("D_808AC270","UNK_TYPE2","",0x2),
- 0x808AC272:("D_808AC272","UNK_TYPE2","",0x2),
- 0x808AC274:("D_808AC274","UNK_TYPE1","",0x1),
- 0x808AC278:("D_808AC278","UNK_TYPE1","",0x1),
- 0x808AC27C:("D_808AC27C","UNK_TYPE1","",0x1),
- 0x808AC280:("D_808AC280","UNK_TYPE1","",0x1),
- 0x808AC284:("D_808AC284","UNK_TYPE1","",0x1),
- 0x808AC288:("D_808AC288","UNK_TYPE1","",0x1),
- 0x808AC28C:("D_808AC28C","UNK_TYPE4","",0x4),
- 0x808AC2A4:("D_808AC2A4","UNK_TYPE1","",0x1),
- 0x808AC2AC:("D_808AC2AC","UNK_TYPE1","",0x1),
- 0x808AC2B8:("D_808AC2B8","UNK_TYPE1","",0x1),
- 0x808AC2C4:("D_808AC2C4","UNK_TYPE1","",0x1),
- 0x808AC2D0:("D_808AC2D0","char","[]",0x1),
- 0x808AC2E0:("D_808AC2E0","char","[]",0x1),
- 0x808AC2F0:("D_808AC2F0","char","[]",0x1),
+ 0x808AC030:("sAnimationsCuriosityShopMan","UNK_TYPE1","",0x1),
+ 0x808AC100:("sAnimationsPartTimeWorker","UNK_TYPE1","",0x1),
+ 0x808AC1C0:("sObjectIds","UNK_TYPE1","",0x1),
+ 0x808AC1C4:("sAnimations","UNK_TYPE1","",0x1),
+ 0x808AC1CC:("sShops","UNK_TYPE1","",0x1),
+ 0x808AC254:("sWelcomeHumanTextIds","UNK_TYPE2","",0x2),
+ 0x808AC258:("sTalkOptionTextIds","UNK_TYPE2","",0x2),
+ 0x808AC25C:("sWelcomeGoronFirstTimeTextIds","UNK_TYPE2","",0x2),
+ 0x808AC260:("sWelcomeZoraFirstTimeTextIds","UNK_TYPE2","",0x2),
+ 0x808AC264:("sWelcomeDekuFirstTimeTextIds","UNK_TYPE2","",0x2),
+ 0x808AC268:("sWelcomeGoronTextIds","UNK_TYPE2","",0x2),
+ 0x808AC26C:("sWelcomeZoraTextIds","UNK_TYPE2","",0x2),
+ 0x808AC270:("sWelcomeDekuTextIds","UNK_TYPE2","",0x2),
+ 0x808AC274:("sNeedEmptyBottleTextIds","UNK_TYPE1","",0x1),
+ 0x808AC278:("sNeedRupeesTextIds","UNK_TYPE1","",0x1),
+ 0x808AC27C:("sNoRoomTextIds","UNK_TYPE1","",0x1),
+ 0x808AC280:("sBuySuccessTextIds","UNK_TYPE1","",0x1),
+ 0x808AC284:("sCannotGetNowTextIds","UNK_TYPE1","",0x1),
+ 0x808AC288:("sInitChain","UNK_TYPE1","",0x1),
+ 0x808AC28C:("sSelectedItemPosition","UNK_TYPE4","",0x4),
+ 0x808AC2A4:("sInitFuncs","UNK_TYPE1","",0x1),
+ 0x808AC2AC:("sPartTimeWorkerFocusOffset","UNK_TYPE1","",0x1),
+ 0x808AC2B8:("sCuriosityShopManEyeTextures","UNK_TYPE1","",0x1),
+ 0x808AC2C4:("sPartTimeWorkerEyeTextures","UNK_TYPE1","",0x1),
+ 0x808AC2D0:("filename1","char","[]",0x1),
+ 0x808AC2E0:("filename2","char","[]",0x1),
+ 0x808AC2F0:("filename3","char","[]",0x1),
0x808AC300:("jtbl_D_808AC300","UNK_PTR","",0x4),
0x808AC32C:("jtbl_D_808AC32C","UNK_PTR","",0x4),
0x808AC34C:("D_808AC34C","f32","",0x4),