diff --git a/assets/xml/objects/object_dy_obj.xml b/assets/xml/objects/object_dy_obj.xml
index 91b9a55fbd..37fef4ab19 100644
--- a/assets/xml/objects/object_dy_obj.xml
+++ b/assets/xml/objects/object_dy_obj.xml
@@ -1,51 +1,62 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -55,42 +66,46 @@
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/xml/objects/object_efc_tw.xml b/assets/xml/objects/object_efc_tw.xml
index a7ca81b55a..c28ae3c81f 100644
--- a/assets/xml/objects/object_efc_tw.xml
+++ b/assets/xml/objects/object_efc_tw.xml
@@ -1,13 +1,16 @@
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/include/z64save.h b/include/z64save.h
index 1db5a566df..7d1bc781d6 100644
--- a/include/z64save.h
+++ b/include/z64save.h
@@ -650,11 +650,14 @@ typedef enum {
#define WEEKEVENTREG_CLOCK_TOWER_OPENED PACK_WEEKEVENTREG_FLAG(8, 0x40)
#define WEEKEVENTREG_08_80 PACK_WEEKEVENTREG_FLAG(8, 0x80)
+
+// This 5 flags are managed in a special way by EnElfgrp
#define WEEKEVENTREG_09_01 PACK_WEEKEVENTREG_FLAG(9, 0x01)
#define WEEKEVENTREG_09_02 PACK_WEEKEVENTREG_FLAG(9, 0x02)
#define WEEKEVENTREG_09_04 PACK_WEEKEVENTREG_FLAG(9, 0x04)
#define WEEKEVENTREG_09_08 PACK_WEEKEVENTREG_FLAG(9, 0x08)
#define WEEKEVENTREG_09_10 PACK_WEEKEVENTREG_FLAG(9, 0x10)
+
#define WEEKEVENTREG_09_20 PACK_WEEKEVENTREG_FLAG(9, 0x20)
#define WEEKEVENTREG_09_40 PACK_WEEKEVENTREG_FLAG(9, 0x40)
#define WEEKEVENTREG_09_80 PACK_WEEKEVENTREG_FLAG(9, 0x80)
@@ -795,7 +798,7 @@ typedef enum {
#define WEEKEVENTREG_22_40 PACK_WEEKEVENTREG_FLAG(22, 0x40)
#define WEEKEVENTREG_22_80 PACK_WEEKEVENTREG_FLAG(22, 0x80)
#define WEEKEVENTREG_23_01 PACK_WEEKEVENTREG_FLAG(23, 0x01)
-#define WEEKEVENTREG_23_02 PACK_WEEKEVENTREG_FLAG(23, 0x02)
+#define WEEKEVENTREG_OBTAINED_GREAT_SPIN_ATTACK PACK_WEEKEVENTREG_FLAG(23, 0x02)
#define WEEKEVENTREG_23_04 PACK_WEEKEVENTREG_FLAG(23, 0x04)
#define WEEKEVENTREG_23_08 PACK_WEEKEVENTREG_FLAG(23, 0x08)
#define WEEKEVENTREG_23_10 PACK_WEEKEVENTREG_FLAG(23, 0x10)
@@ -1631,6 +1634,9 @@ typedef enum {
/* 3 */ DUNGEON_INDEX_STONE_TOWER_TEMPLE // Also applies to Inverted Stone Tower Temple
} DungeonIndex;
+#define STRAY_FAIRY_TOTAL 25 // total number of stray fairies, including those already in the Great Fairy Fountain
+#define STRAY_FAIRY_SCATTERED_TOTAL 15 // original number of stray fairies in one dungeon area
+
void Sram_ActivateOwl(u8 owlId);
void Sram_ClearFlagsAtDawnOfTheFirstDay(void);
void Sram_SaveEndOfCycle(struct PlayState* play);
diff --git a/spec b/spec
index eb09f058f6..d7d51ec20a 100644
--- a/spec
+++ b/spec
@@ -2365,8 +2365,7 @@ beginseg
name "ovl_Bg_Dy_Yoseizo"
compress
include "build/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.o"
- include "build/data/ovl_Bg_Dy_Yoseizo/ovl_Bg_Dy_Yoseizo.data.o"
- include "build/data/ovl_Bg_Dy_Yoseizo/ovl_Bg_Dy_Yoseizo.reloc.o"
+ include "build/src/overlays/actors/ovl_Bg_Dy_Yoseizo/ovl_Bg_Dy_Yoseizo_reloc.o"
endseg
beginseg
diff --git a/src/code/z_actor.c b/src/code/z_actor.c
index a69dada412..10f782e25d 100644
--- a/src/code/z_actor.c
+++ b/src/code/z_actor.c
@@ -725,7 +725,7 @@ void Target_Update(TargetContext* targetCtx, Player* player, Actor* lockOnActor,
/* Start of Flags section */
/**
- * Tests if current scene switch flag is set.
+ * Tests if a current scene switch flag is set.
*/
s32 Flags_GetSwitch(PlayState* play, s32 flag) {
if ((flag >= 0) && (flag < 0x80)) {
@@ -735,7 +735,7 @@ s32 Flags_GetSwitch(PlayState* play, s32 flag) {
}
/**
- * Sets current scene switch flag.
+ * Sets a current scene switch flag.
*/
void Flags_SetSwitch(PlayState* play, s32 flag) {
if ((flag >= 0) && (flag < 0x80)) {
@@ -744,7 +744,7 @@ void Flags_SetSwitch(PlayState* play, s32 flag) {
}
/**
- * Unsets current scene switch flag.
+ * Unsets a current scene switch flag.
*/
void Flags_UnsetSwitch(PlayState* play, s32 flag) {
if ((flag >= 0) && (flag < 0x80)) {
@@ -753,77 +753,77 @@ void Flags_UnsetSwitch(PlayState* play, s32 flag) {
}
/**
- * Tests if current scene chest flag is set.
+ * Tests if a current scene chest flag is set.
*/
s32 Flags_GetTreasure(PlayState* play, s32 flag) {
return play->actorCtx.sceneFlags.chest & (1 << flag);
}
/**
- * Sets current scene chest flag.
+ * Sets a current scene chest flag.
*/
void Flags_SetTreasure(PlayState* play, s32 flag) {
play->actorCtx.sceneFlags.chest |= (1 << flag);
}
/**
- * Overrides the all the chest flags.
+ * Overrides all the current scene chest flags.
*/
void Flags_SetAllTreasure(PlayState* play, s32 flag) {
play->actorCtx.sceneFlags.chest = flag;
}
/**
- * Returns all the chest flags.
+ * Returns all the current scene chest flags.
*/
s32 Flags_GetAllTreasure(PlayState* play) {
return play->actorCtx.sceneFlags.chest;
}
/**
- * Tests if current scene clear flag is set.
+ * Tests if a current scene clear flag is set.
*/
s32 Flags_GetClear(PlayState* play, s32 roomNumber) {
return play->actorCtx.sceneFlags.clearedRoom & (1 << roomNumber);
}
/**
- * Sets current scene clear flag.
+ * Sets a current scene clear flag.
*/
void Flags_SetClear(PlayState* play, s32 roomNumber) {
play->actorCtx.sceneFlags.clearedRoom |= (1 << roomNumber);
}
/**
- * Unsets current scene clear flag.
+ * Unsets a current scene clear flag.
*/
void Flags_UnsetClear(PlayState* play, s32 roomNumber) {
play->actorCtx.sceneFlags.clearedRoom &= ~(1 << roomNumber);
}
/**
- * Tests if current scene temp clear flag is set.
+ * Tests if a current scene temp clear flag is set.
*/
s32 Flags_GetClearTemp(PlayState* play, s32 roomNumber) {
return play->actorCtx.sceneFlags.clearedRoomTemp & (1 << roomNumber);
}
/**
- * Sets current scene temp clear flag.
+ * Sets a current scene temp clear flag.
*/
void Flags_SetClearTemp(PlayState* play, s32 roomNumber) {
play->actorCtx.sceneFlags.clearedRoomTemp |= (1 << roomNumber);
}
/**
- * Unsets current scene temp clear flag.
+ * Unsets a current scene temp clear flag.
*/
void Flags_UnsetClearTemp(PlayState* play, s32 roomNumber) {
play->actorCtx.sceneFlags.clearedRoomTemp &= ~(1 << roomNumber);
}
/**
- * Tests if current scene collectible flag is set.
+ * Tests if a current scene collectible flag is set.
*/
s32 Flags_GetCollectible(PlayState* play, s32 flag) {
if ((flag > 0) && (flag < 0x80)) {
@@ -833,7 +833,7 @@ s32 Flags_GetCollectible(PlayState* play, s32 flag) {
}
/**
- * Sets current scene collectible flag.
+ * Sets a current scene collectible flag.
*/
void Flags_SetCollectible(PlayState* play, s32 flag) {
if ((flag > 0) && (flag < 0x80)) {
diff --git a/src/code/z_en_item00.c b/src/code/z_en_item00.c
index 55ab1a7082..f9f5df5a83 100644
--- a/src/code/z_en_item00.c
+++ b/src/code/z_en_item00.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "overlays/actors/ovl_En_Elforg/z_en_elforg.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_gi_hearts/object_gi_hearts.h"
#include "overlays/actors/ovl_En_Elf/z_en_elf.h"
@@ -935,9 +936,9 @@ Actor* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, u32 params) {
SoundSource_PlaySfxAtFixedWorldPos(play, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY);
}
} else {
- spawnedActor =
- Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELFORG, spawnPos->x, spawnPos->y + 40.0f, spawnPos->z, 0, 0,
- 0, STRAY_FAIRY_PARAMS(((param7F00 >> 8) & 0x7F), 0, STRAY_FAIRY_TYPE_COLLECTIBLE));
+ spawnedActor = Actor_Spawn(
+ &play->actorCtx, play, ACTOR_EN_ELFORG, spawnPos->x, spawnPos->y + 40.0f, spawnPos->z, 0, 0, 0,
+ STRAY_FAIRY_PARAMS((param7F00 >> 8) & 0x7F, STRAY_FAIRY_AREA_CLOCK_TOWN, STRAY_FAIRY_TYPE_COLLECTIBLE));
if (param20000 == 0) {
if (!Flags_GetCollectible(play, (param7F00 >> 8) & 0x7F)) {
SoundSource_PlaySfxAtFixedWorldPos(play, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY);
@@ -993,9 +994,9 @@ Actor* Item_DropCollectible2(PlayState* play, Vec3f* spawnPos, s32 params) {
spawnedActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, spawnPos->x, spawnPos->y + 40.0f,
spawnPos->z, 0, 0, 0, FAIRY_PARAMS(FAIRY_TYPE_2, true, param7F00 >> 8));
} else {
- spawnedActor =
- Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELFORG, spawnPos->x, spawnPos->y + 40.0f, spawnPos->z, 0, 0,
- 0, STRAY_FAIRY_PARAMS(((param7F00 >> 8) & 0x7F), 0, STRAY_FAIRY_TYPE_COLLECTIBLE));
+ spawnedActor = Actor_Spawn(
+ &play->actorCtx, play, ACTOR_EN_ELFORG, spawnPos->x, spawnPos->y + 40.0f, spawnPos->z, 0, 0, 0,
+ STRAY_FAIRY_PARAMS((param7F00 >> 8) & 0x7F, STRAY_FAIRY_AREA_CLOCK_TOWN, STRAY_FAIRY_TYPE_COLLECTIBLE));
}
if (Flags_GetCollectible(play, (param7F00 >> 8) & 0x7F) == 0) {
SoundSource_PlaySfxAtFixedWorldPos(play, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY);
diff --git a/src/code/z_sram_NES.c b/src/code/z_sram_NES.c
index 8d382e5db3..c5fe03475e 100644
--- a/src/code/z_sram_NES.c
+++ b/src/code/z_sram_NES.c
@@ -97,7 +97,8 @@ u16 sPersistentCycleWeekEventRegs[ARRAY_COUNT(gSaveContext.save.saveInfo.weekEve
/* 20 */ 0,
/* 21 */ 0,
/* 22 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_22_02) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_22_80),
- /* 23 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_23_02) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_23_80),
+ /* 23 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_OBTAINED_GREAT_SPIN_ATTACK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_23_80),
/* 24 */ PERSISTENT_WEEKEVENTREG_ALT(WEEKEVENTREG_24_02) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_24_80),
/* 25 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_25_01),
/* 26 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_26_40),
diff --git a/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c b/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c
index 332e4e5430..4045303426 100644
--- a/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c
+++ b/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c
@@ -5,6 +5,7 @@
*/
#include "z_bg_dy_yoseizo.h"
+#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
#define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_2000000)
@@ -13,19 +14,17 @@
void BgDyYoseizo_Init(Actor* thisx, PlayState* play);
void BgDyYoseizo_Destroy(Actor* thisx, PlayState* play);
void BgDyYoseizo_Update(Actor* thisx, PlayState* play);
+void BgDyYoseizo_Draw(Actor* thisx, PlayState* play);
-void func_80A0AE1C(BgDyYoseizo* this, PlayState* play);
-void func_80A0B078(BgDyYoseizo* this, PlayState* play);
void func_80A0B184(BgDyYoseizo* this, PlayState* play);
-void func_80A0B290(BgDyYoseizo* this, PlayState* play);
-void func_80A0B35C(BgDyYoseizo* this, PlayState* play);
-void func_80A0B500(BgDyYoseizo* this, PlayState* play);
-void func_80A0B5F0(BgDyYoseizo* this, PlayState* play);
-void func_80A0B75C(BgDyYoseizo* this, PlayState* play);
-void func_80A0B8CC(BgDyYoseizo* this, PlayState* play);
void func_80A0BB08(BgDyYoseizo* this, PlayState* play);
-#if 0
+/* Effects functions */
+void BgDyYoseizo_SpawnEffect(BgDyYoseizo* this, Vec3f* initPos, Vec3f* initVelocity, Vec3f* accel,
+ Color_RGB8* primColor, Color_RGB8* envColor, f32 scale, s16 life, s16 type);
+void BgDyYoseizo_UpdateEffects(BgDyYoseizo* this, PlayState* play);
+void BgDyYoseizo_DrawEffects(BgDyYoseizo* this, PlayState* play);
+
ActorInit Bg_Dy_Yoseizo_InitVars = {
ACTOR_BG_DY_YOSEIZO,
ACTORCAT_PROP,
@@ -38,56 +37,730 @@ ActorInit Bg_Dy_Yoseizo_InitVars = {
(ActorFunc)NULL,
};
-#endif
+typedef enum GreatFairyAnimation {
+ /* 0 */ GREATFAIRY_ANIM_START_GIVING_UPGRADE,
+ /* 1 */ GREATFAIRY_ANIM_GIVING_UPGRADE,
+ /* 2 */ GREATFAIRY_ANIM_SPIN_LAY_DOWN,
+ /* 3 */ GREATFAIRY_ANIM_LAY_DOWN_TRANSITION,
+ /* 4 */ GREATFAIRY_ANIM_LAYING_DOWN,
+ /* 5 */ GREATFAIRY_ANIM_SHOWING_ITEM,
+ /* 6 */ GREATFAIRY_ANIM_ARMS_FOLDED,
+ /* 7 */ GREATFAIRY_ANIM_CLAPPING,
+ /* 8 */ GREATFAIRY_ANIM_TEACH_SPIN_ATTACK,
+ /* 9 */ GREATFAIRY_ANIM_MAX
+} GreatFairyAnimation;
-extern UNK_TYPE D_06008090;
-extern UNK_TYPE D_0600D228;
-extern UNK_TYPE D_0601C6F4;
+static AnimationHeader* sAnimations[GREATFAIRY_ANIM_MAX] = {
+ &gGreatFairyStartGivingUpgradeAnim, // GREATFAIRY_ANIM_START_GIVING_UPGRADE
+ &gGreatFairyGivingUpgradeAnim, // GREATFAIRY_ANIM_GIVING_UPGRADE
+ &gGreatFairySpinLayDownAnim, // GREATFAIRY_ANIM_SPIN_LAY_DOWN
+ &gGreatFairyLayDownTransitionAnim, // GREATFAIRY_ANIM_LAY_DOWN_TRANSITION
+ &gGreatFairyLayingDownAnim, // GREATFAIRY_ANIM_LAYING_DOWN
+ &gGreatFairyShowingItemAnim, // GREATFAIRY_ANIM_SHOWING_ITEM
+ &gGreatFairyArmsFoldedAnim, // GREATFAIRY_ANIM_ARMS_FOLDED
+ &gGreatFairyClappingAnim, // GREATFAIRY_ANIM_CLAPPING
+ &gGreatFairyTeachSpinAttackAnim, // GREATFAIRY_ANIM_TEACH_SPIN_ATTACK
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/BgDyYoseizo_Init.s")
+void BgDyYoseizo_Init(Actor* thisx, PlayState* play) {
+ BgDyYoseizo* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/BgDyYoseizo_Destroy.s")
+ this->unk2EC = this->actor.world.pos.y + 40.0f;
+ this->actor.focus.pos = this->actor.world.pos;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0A96C.s")
+ SkelAnime_InitFlex(play, &this->skelAnime, &gGreatFairySkel, &gGreatFairyShowingItemAnim, this->jointTable,
+ this->morphTable, GREAT_FAIRY_LIMB_MAX);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0A9E4.s")
+ this->actionFunc = func_80A0BB08;
+ Actor_SetScale(&this->actor, 0.0f);
+ this->eyeIndex = 0;
+ this->mouthIndex = 0;
+ this->blinkTimer = 0;
+ this->unk2F8 = 0;
+ GREAT_FAIRY_ROTZ(&this->actor) = 1;
+ this->unk302 = 0;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0AA40.s")
+void BgDyYoseizo_Destroy(Actor* thisx, PlayState* play) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0AD50.s")
+// Has no visible effect since no segment is set for manually-controllable eye textures
+void BgDyYoseizo_UpdateEyes(BgDyYoseizo* this) {
+ if (this->blinkTimer != 0) {
+ this->blinkTimer--;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0AE1C.s")
+ if (this->blinkTimer == 0) {
+ this->eyeIndex++;
+ if (this->eyeIndex >= 3) {
+ this->eyeIndex = 0;
+ this->blinkTimer = (s32)Rand_ZeroFloat(60.0f) + 20;
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0AFDC.s")
+void BgDyYoseizo_Bob(BgDyYoseizo* this, PlayState* play) {
+ this->actor.shape.yOffset = Math_SinS(play->gameplayFrames * 1000) * 15.0f;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0B078.s")
+typedef enum GreatFairyEffectTrajectory {
+ /* 0 */ GREAT_FAIRY_EFFECT_TRAJECTORY_RADIANT, // Dispersing particles, in the Great Fairy's signature colour.
+ /* 2 */ GREAT_FAIRY_EFFECT_TRAJECTORY_FAST_RADIANT = 2, // As above, but initially move 10 times faster.
+ /* 5 */ GREAT_FAIRY_EFFECT_TRAJECTORY_CONVERGE_ON_PLAYER = 5 // Similar to OoT's healing effect, fixed colour.
+} GreatFairyEffectTrajectory;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0B184.s")
+/**
+ * Spawn particle effects; see `GreatFairyEffectTrajectory` enum for details
+ *
+ * @param trajectoryType use the `GreatFairyEffectTrajectory` enum.
+ * @param count number to spawn.
+ */
+void BgDyYoseizo_SpawnEffects(BgDyYoseizo* this, s16 trajectoryType, s32 count) {
+ static Color_RGB8 sEffectPrimColors[] = {
+ { 255, 235, 220 }, // Magic
+ { 255, 220, 220 }, // Power
+ { 220, 255, 220 }, // Wisdom
+ { 220, 220, 255 }, // Courage
+ { 255, 255, 200 }, // Kindness
+ { 255, 255, 170 }, // GREAT_FAIRY_EFFECT_TRAJECTORY_CONVERGE_ON_PLAYER
+ };
+ static Color_RGB8 sEffectEnvColors[] = {
+ { 255, 150, 0 }, // Magic
+ { 255, 0, 0 }, // Power
+ { 0, 255, 0 }, // Wisdom
+ { 0, 0, 255 }, // Courage
+ { 255, 255, 0 }, // Kindness
+ { 255, 100, 255 }, // GREAT_FAIRY_EFFECT_TRAJECTORY_CONVERGE_ON_PLAYER
+ };
+ Vec3f velocity;
+ Vec3f accel;
+ Vec3f pos;
+ Color_RGB8 primColor;
+ Color_RGB8 envColor;
+ f32 spawnHeightVariation;
+ f32 scale;
+ s32 effectType;
+ s32 life;
+ s32 i;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0B290.s")
+ if (this->actor.scale.y < 0.01f) {
+ return;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0B35C.s")
+ spawnHeightVariation = this->actor.scale.y * 3500.0f;
+ accel.x = Rand_ZeroOne() - 0.5f;
+ accel.y = Rand_ZeroOne() - 0.5f;
+ accel.z = Rand_ZeroOne() - 0.5f;
+ velocity.x = accel.x * 10.0f;
+ velocity.y = accel.y * 10.0f;
+ velocity.z = accel.z * 10.0f;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0B500.s")
+ for (i = 0; i < count; i++) {
+ switch (trajectoryType) {
+ case GREAT_FAIRY_EFFECT_TRAJECTORY_FAST_RADIANT:
+ scale = 1.0f;
+ life = 90;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0B5F0.s")
+ velocity.x = accel.x * 100.0f;
+ velocity.y = accel.y * 100.0f;
+ velocity.z = accel.z * 100.0f;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0B75C.s")
+ effectType = GREAT_FAIRY_GET_TYPE(&this->actor);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0B834.s")
+ pos.x = this->actor.world.pos.x;
+ pos.y = this->actor.world.pos.y + spawnHeightVariation +
+ (Rand_ZeroOne() - 0.5f) * (spawnHeightVariation * 0.5f);
+ pos.z = this->actor.world.pos.z + 30.0f;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0B8CC.s")
+ case GREAT_FAIRY_EFFECT_TRAJECTORY_RADIANT:
+ scale = 1.0f;
+ life = 90;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0BB08.s")
+ effectType = GREAT_FAIRY_GET_TYPE(&this->actor);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/BgDyYoseizo_Update.s")
+ pos.x = this->actor.world.pos.x;
+ pos.y = this->actor.world.pos.y + spawnHeightVariation +
+ (Rand_ZeroOne() - 0.5f) * (spawnHeightVariation * 0.5f);
+ pos.z = this->actor.world.pos.z + 30.0f;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0BCD8.s")
+ default: // all become convergent type
+ scale = 0.2f;
+ life = 50;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0BD40.s")
+ effectType = GREAT_FAIRY_EFFECT_TRAJECTORY_CONVERGE_ON_PLAYER;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0BE60.s")
+ pos.x = Rand_CenteredFloat(10.0f) + this->actor.world.pos.x;
+ pos.y = this->actor.world.pos.y + spawnHeightVariation + 50.0f +
+ (Rand_ZeroOne() - 0.5f) * (spawnHeightVariation * 0.1f);
+ pos.z = this->actor.world.pos.z + 30.0f;
+ break;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0BF70.s")
+ primColor.r = sEffectPrimColors[effectType].r;
+ primColor.g = sEffectPrimColors[effectType].g;
+ primColor.b = sEffectPrimColors[effectType].b;
+ envColor.r = sEffectEnvColors[effectType].r;
+ envColor.g = sEffectEnvColors[effectType].g;
+ envColor.b = sEffectEnvColors[effectType].b;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dy_Yoseizo/func_80A0C270.s")
+ BgDyYoseizo_SpawnEffect(this, &pos, &velocity, &accel, &primColor, &envColor, scale, life, effectType);
+ }
+}
+
+void func_80A0AD50(BgDyYoseizo* this) {
+ f32 scale = this->actor.scale.x;
+ f32 heightTarget = this->actor.home.pos.y + 40.0f;
+
+ Math_ApproachF(&this->actor.world.pos.y, heightTarget, this->unk2F0, 100.0f);
+ Math_ApproachF(&scale, 0.035f, this->unk2F4, 0.005f);
+ Math_ApproachF(&this->unk2F0, 0.8f, 0.1f, 0.02f);
+ Math_ApproachF(&this->unk2F4, 0.2f, 0.03f, 0.05f);
+ BgDyYoseizo_SpawnEffects(this, GREAT_FAIRY_EFFECT_TRAJECTORY_RADIANT, 2);
+ Actor_SetScale(&this->actor, scale);
+}
+
+void func_80A0AE1C(BgDyYoseizo* this, PlayState* play) {
+ f32 scale = this->actor.scale.x;
+ f32 heightTarget = this->actor.home.pos.y;
+
+ if (scale < 0.003f) {
+ this->actionFunc = func_80A0BB08;
+ Actor_SetScale(&this->actor, 0.0f);
+ this->unk2F0 = 0.0f;
+ this->unk2F4 = 0.0f;
+ this->unk2F8 = 0;
+
+ if (GREAT_FAIRY_GET_TYPE(&this->actor) <= GREAT_FAIRY_TYPE_COURAGE) {
+ Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x,
+ this->actor.world.pos.y + 20.0f, this->actor.world.pos.z, 0, 0, 0,
+ GREAT_FAIRY_GET_TYPE(&this->actor) + DEMO_EFFECT_TYPE_LIGHT_BASE);
+ } else {
+ Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x,
+ this->actor.world.pos.y + 20.0f, this->actor.world.pos.z, 0, 0, 0,
+ DEMO_EFFECT_TYPE_LIGHT_DARK_YELLOW);
+ }
+ Audio_PlaySfx(NA_SE_SY_WHITE_OUT_T);
+ } else {
+ Math_ApproachF(&this->actor.world.pos.y, heightTarget, this->unk2F0, 100.0f);
+ Math_ApproachZeroF(&scale, this->unk2F4, 0.005f);
+ Math_ApproachF(&this->unk2F0, 0.8f, 0.1f, 0.02f);
+ Math_ApproachF(&this->unk2F4, 0.2f, 0.03f, 0.05f);
+
+ this->actor.shape.rot.y += this->unk2F8;
+ if (this->unk2F8 < 0x1770) {
+ this->unk2F8 += 0x12C;
+ }
+
+ BgDyYoseizo_SpawnEffects(this, GREAT_FAIRY_EFFECT_TRAJECTORY_RADIANT, 2);
+ Actor_SetScale(&this->actor, scale);
+ }
+}
+
+void func_80A0AFDC(BgDyYoseizo* this) {
+ Animation_Change(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_SPIN_LAY_DOWN], 0.0f, 46.0f,
+ Animation_GetLastFrame(sAnimations[GREATFAIRY_ANIM_SPIN_LAY_DOWN]), ANIMMODE_ONCE, 0.0f);
+ this->actionFunc = func_80A0AE1C;
+ Actor_PlaySfx(&this->actor, NA_SE_VO_FR_LAUGH_0);
+ Actor_PlaySfx(&this->actor, NA_SE_EV_GREAT_FAIRY_VANISH);
+ this->unk2F8 = 0;
+ this->actor.velocity.y = 0.0f;
+ this->unk2F0 = 0.0f;
+ this->unk2F4 = 0.0f;
+ this->actor.shape.yOffset = 0.0f;
+}
+
+void func_80A0B078(BgDyYoseizo* this, PlayState* play) {
+ BgDyYoseizo_Bob(this, play);
+ SkelAnime_Update(&this->skelAnime);
+
+ if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 7)) {
+ Animation_Change(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_LAYING_DOWN], 1.0f, 0.0f,
+ Animation_GetLastFrame(sAnimations[GREATFAIRY_ANIM_LAYING_DOWN]), ANIMMODE_LOOP, 0.0f);
+ this->actionFunc = func_80A0B184;
+ } else if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 6)) {
+ func_80A0AFDC(this);
+ }
+}
+
+void func_80A0B184(BgDyYoseizo* this, PlayState* play) {
+ BgDyYoseizo_Bob(this, play);
+ SkelAnime_Update(&this->skelAnime);
+
+ if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 8)) {
+ Animation_Change(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_SHOWING_ITEM], 1.0f, 0.0f,
+ Animation_GetLastFrame(sAnimations[GREATFAIRY_ANIM_SHOWING_ITEM]), ANIMMODE_LOOP, 0.0f);
+ this->actionFunc = func_80A0B078;
+ } else if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 6)) {
+ func_80A0AFDC(this);
+ }
+}
+
+void func_80A0B290(BgDyYoseizo* this, PlayState* play) {
+ BgDyYoseizo_Bob(this, play);
+ SkelAnime_Update(&this->skelAnime);
+
+ if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 7)) {
+ Animation_Change(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_LAYING_DOWN], 1.0f, 0.0f,
+ Animation_GetLastFrame(sAnimations[GREATFAIRY_ANIM_LAYING_DOWN]), ANIMMODE_LOOP, -10.0f);
+ this->actionFunc = func_80A0B184;
+ this->mouthIndex = 0;
+ }
+}
+
+void func_80A0B35C(BgDyYoseizo* this, PlayState* play) {
+ BgDyYoseizo_Bob(this, play);
+ SkelAnime_Update(&this->skelAnime);
+
+ if (this->timer == 60) {
+ if (!Flags_GetSwitch(play, GREAT_FAIRY_GET_SWITCHFLAG(&this->actor))) {
+ switch (GREAT_FAIRY_GET_TYPE(&this->actor)) {
+ case GREAT_FAIRY_TYPE_MAGIC:
+ if (gSaveContext.save.saveInfo.playerData.isMagicAcquired != true) {
+ gSaveContext.save.saveInfo.playerData.isMagicAcquired = true;
+ gSaveContext.magicFillTarget = MAGIC_NORMAL_METER;
+ }
+ break;
+
+ case GREAT_FAIRY_TYPE_WISDOM:
+ if (gSaveContext.save.saveInfo.playerData.isDoubleMagicAcquired != true) {
+ gSaveContext.save.saveInfo.playerData.isDoubleMagicAcquired = true;
+ gSaveContext.magicFillTarget = MAGIC_DOUBLE_METER;
+ gSaveContext.save.saveInfo.playerData.magicLevel = 0;
+ }
+ break;
+
+ case GREAT_FAIRY_TYPE_COURAGE:
+ if (gSaveContext.save.saveInfo.playerData.doubleDefense != true) {
+ gSaveContext.save.saveInfo.playerData.doubleDefense = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ Interface_SetHudVisibility(9);
+ }
+
+ if ((this->timer < 50) && (GREAT_FAIRY_GET_TYPE(&this->actor) == GREAT_FAIRY_TYPE_COURAGE)) {
+ if (gSaveContext.save.saveInfo.inventory.defenseHearts < 20) {
+ gSaveContext.save.saveInfo.inventory.defenseHearts++;
+ }
+ }
+
+ if (this->timer == 50) {
+ gSaveContext.healthAccumulator = 0x140;
+ Magic_Add(play, MAGIC_FILL_TO_CAPACITY);
+ }
+
+ if (this->timer == 0) {
+ this->beam->trigger = true;
+ this->actionFunc = func_80A0B290;
+ }
+}
+
+void func_80A0B500(BgDyYoseizo* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+
+ BgDyYoseizo_Bob(this, play);
+
+ if (SkelAnime_Update(&this->skelAnime)) {
+ Vec3f pos;
+
+ Animation_Change(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_GIVING_UPGRADE], 1.0f, 0.0f,
+ Animation_GetLastFrame(sAnimations[GREATFAIRY_ANIM_GIVING_UPGRADE]), ANIMMODE_LOOP, 0.0f);
+ this->actionFunc = func_80A0B35C;
+ pos.x = player->actor.world.pos.x;
+ pos.y = player->actor.world.pos.y + 200.0f;
+ pos.z = player->actor.world.pos.z;
+ this->beam = (EnDyExtra*)Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_DY_EXTRA, pos.x,
+ pos.y, pos.z, 0, 0, 0, GREAT_FAIRY_GET_TYPE(&this->actor));
+ this->timer = 120;
+ }
+}
+
+void func_80A0B5F0(BgDyYoseizo* this, PlayState* play) {
+ BgDyYoseizo_Bob(this, play);
+
+ if (SkelAnime_Update(&this->skelAnime)) {
+ Animation_Change(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_LAYING_DOWN], 1.0f, 0.0f,
+ Animation_GetLastFrame(sAnimations[GREATFAIRY_ANIM_LAYING_DOWN]), ANIMMODE_LOOP, 0.0f);
+ }
+
+ if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 5)) {
+ Animation_Change(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_START_GIVING_UPGRADE], 1.0f, 0.0f,
+ Animation_GetLastFrame(sAnimations[GREATFAIRY_ANIM_START_GIVING_UPGRADE]), ANIMMODE_ONCE,
+ -5.0f);
+ Actor_PlaySfx(&this->actor, NA_SE_VO_FR_SMILE_0);
+ this->mouthIndex = 1;
+ this->eyeIndex = 0;
+ this->actionFunc = func_80A0B500;
+ }
+
+ if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 6)) {
+ func_80A0AFDC(this);
+ }
+
+ BgDyYoseizo_UpdateEyes(this);
+}
+
+void func_80A0B75C(BgDyYoseizo* this, PlayState* play) {
+ func_80A0AD50(this);
+ SkelAnime_Update(&this->skelAnime);
+
+ if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 4)) {
+ this->actor.shape.rot.y = 0;
+ this->actionFunc = func_80A0B5F0;
+ Animation_Change(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_LAY_DOWN_TRANSITION], 1.0f, 2.0f,
+ Animation_GetLastFrame(sAnimations[GREATFAIRY_ANIM_LAY_DOWN_TRANSITION]), ANIMMODE_ONCE, 0.0f);
+ Actor_PlaySfx(&this->actor, NA_SE_VO_FR_SMILE_0);
+ this->unk2F8 = 0;
+ }
+}
+
+void func_80A0B834(BgDyYoseizo* this) {
+ this->actor.draw = BgDyYoseizo_Draw;
+ Animation_Change(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_SPIN_LAY_DOWN], 1.0f, 0.0f,
+ Animation_GetLastFrame(sAnimations[GREATFAIRY_ANIM_SPIN_LAY_DOWN]), ANIMMODE_ONCE, 0.0f);
+ Actor_PlaySfx(&this->actor, NA_SE_VO_FR_LAUGH_0);
+ Actor_PlaySfx(&this->actor, NA_SE_EV_GREAT_FAIRY_APPEAR);
+ BgDyYoseizo_SpawnEffects(this, GREAT_FAIRY_EFFECT_TRAJECTORY_FAST_RADIANT, 30);
+}
+
+void BgDyYoseizo_TrainPlayer(BgDyYoseizo* this, PlayState* play) {
+ s16 csId;
+ s32 pad;
+ Player* player = GET_PLAYER(play);
+
+ SkelAnime_Update(&this->skelAnime);
+
+ csId = 0;
+ if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103)) {
+ csId = play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id;
+ Cutscene_ActorTranslateAndYaw(&this->actor, play, Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103));
+ } else {
+ if (GREAT_FAIRY_ROTZ(&this->actor) != 0) {
+ this->actor.home.pos.x = player->actor.world.pos.x;
+ this->actor.home.pos.z = player->actor.world.pos.z;
+ GREAT_FAIRY_ROTZ(&this->actor) = 0;
+ } else {
+ player->actor.world.pos.x = this->actor.home.pos.x;
+ player->actor.world.pos.z = this->actor.home.pos.z;
+ }
+
+ if (this->unk302 & 1) {
+ if (this->timer == 0) {
+ if (CutsceneManager_IsNext(this->actor.csId)) {
+ CutsceneManager_StartWithPlayerCs(this->actor.csId, &this->actor);
+ this->unk302 &= ~1;
+ } else {
+ CutsceneManager_Queue(this->actor.csId);
+ }
+ }
+ } else if (!(this->unk302 & 2) && (player->meleeWeaponState != 0)) {
+ if (player->meleeWeaponAnimation >= PLAYER_MWA_SPIN_ATTACK_1H) {
+ if (player->unk_B08 >= 0.85f) {
+ this->unk302 |= 1;
+ this->unk302 |= 2;
+ if (play->msgCtx.currentTextId == 0x59A) {
+ Message_CloseTextbox(play);
+ }
+ this->timer = 20;
+ return;
+ }
+ }
+
+ if (play->msgCtx.currentTextId != 0x59A) {
+ // "Hold B and then release"
+ Message_StartTextbox(play, 0x59A, &this->actor);
+ }
+ }
+ }
+
+ if (csId != this->csId) {
+ switch (csId) {
+ case 9:
+ Animation_PlayLoop(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_ARMS_FOLDED]);
+ break;
+
+ case 10:
+ Animation_PlayLoop(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_CLAPPING]);
+ break;
+
+ case 11:
+ Animation_PlayOnce(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_TEACH_SPIN_ATTACK]);
+ break;
+
+ default:
+ break;
+ }
+
+ this->csId = csId;
+ }
+}
+
+// Choose behaviour?
+void func_80A0BB08(BgDyYoseizo* this, PlayState* play) {
+ if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 2)) {
+ func_80A0B834(this);
+ this->actionFunc = func_80A0B75C;
+ }
+
+ if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 7)) {
+ this->actor.draw = BgDyYoseizo_Draw;
+ Animation_PlayLoop(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_LAYING_DOWN]);
+ this->actionFunc = func_80A0B184;
+ this->mouthIndex = 0;
+ this->actor.world.pos.y = this->actor.home.pos.y + 40.0f;
+ Actor_SetScale(&this->actor, 0.035f);
+ this->unk2F8 = 0;
+ }
+
+ if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103) &&
+ (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_103)]->id == 9)) {
+ Actor_SetScale(&this->actor, 0.01f);
+ Animation_PlayLoop(&this->skelAnime, sAnimations[GREATFAIRY_ANIM_ARMS_FOLDED]);
+ this->csId = 9;
+ this->actionFunc = BgDyYoseizo_TrainPlayer;
+ this->actor.draw = BgDyYoseizo_Draw;
+ }
+}
+
+void BgDyYoseizo_Update(Actor* thisx, PlayState* play) {
+ BgDyYoseizo* this = THIS;
+
+ this->actionFunc(this, play);
+ Actor_MoveWithGravity(&this->actor);
+
+ DECR(this->timer);
+
+ BgDyYoseizo_UpdateEffects(this, play);
+}
+
+s32 BgDyYoseizo_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
+ BgDyYoseizo* this = THIS;
+
+ if (limbIndex == GREAT_FAIRY_LIMB_TORSO) {
+ rot->x += this->torsoRot.y;
+ }
+
+ if (limbIndex == GREAT_FAIRY_LIMB_HEAD) {
+ rot->x += this->headRot.y;
+ rot->z += this->headRot.z;
+ }
+
+ return false;
+}
+
+/* Colour and shape of eyebrows, hair colour. */
+typedef enum GreatFairyAppearance {
+ /* 0 */ GREAT_FAIRY_APPEARANCE_MAGIC, // Orange
+ /* 1 */ GREAT_FAIRY_APPEARANCE_WISDOM, // Green
+ /* 2 */ GREAT_FAIRY_APPEARANCE_POWER, // Pink
+ /* 3 */ GREAT_FAIRY_APPEARANCE_COURAGE, // Purple
+ /* 4 */ GREAT_FAIRY_APPEARANCE_KINDNESS // Yellow
+} GreatFairyAppearance;
+
+void BgDyYoseizo_Draw(Actor* thisx, PlayState* play) {
+ static TexturePtr sMouthTextures[] = {
+ gGreatFairyMouthClosedTex,
+ gGreatFairyMouthOpenTex,
+ };
+ BgDyYoseizo* this = THIS;
+ GreatFairyAppearance appearance = GREAT_FAIRY_APPEARANCE_MAGIC;
+
+ // The differing eyes and hair colours
+ switch (GREAT_FAIRY_GET_TYPE(&this->actor)) {
+ case GREAT_FAIRY_TYPE_POWER:
+ appearance = GREAT_FAIRY_APPEARANCE_POWER;
+ break;
+
+ case GREAT_FAIRY_TYPE_WISDOM:
+ appearance = GREAT_FAIRY_APPEARANCE_WISDOM;
+ break;
+
+ case GREAT_FAIRY_TYPE_COURAGE:
+ case GREAT_FAIRY_TYPE_KINDNESS:
+ appearance = GREAT_FAIRY_GET_TYPE(&this->actor);
+ break;
+
+ default: // GREAT_FAIRY_APPEARANCE_MAGIC
+ break;
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL25_Opa(play->state.gfxCtx);
+
+ // Set eyes and hair colour, not actually animated.
+ AnimatedMat_DrawStepOpa(play, Lib_SegmentedToVirtual(gGreatFairyAppearenceTexAnim), appearance);
+
+ // Draw mouth
+ {
+ Gfx* gfx = POLY_OPA_DISP;
+ s16 index = this->mouthIndex;
+ TexturePtr mouthTex = Lib_SegmentedToVirtual(sMouthTextures[index]);
+
+ gSPSegment(&gfx[0], 0x09, mouthTex);
+ POLY_OPA_DISP = &gfx[1];
+ }
+
+ SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
+ BgDyYoseizo_OverrideLimbDraw, NULL, &this->actor);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+
+ BgDyYoseizo_DrawEffects(this, play);
+}
+
+/* Effects functions */
+
+void BgDyYoseizo_SpawnEffect(BgDyYoseizo* this, Vec3f* initPos, Vec3f* initVelocity, Vec3f* accel,
+ Color_RGB8* primColor, Color_RGB8* envColor, f32 scale, s16 life, s16 type) {
+ BgDyYoseizoEffect* effect = this->effects;
+ s16 i;
+
+ for (i = 0; i < BG_DY_YOSEIZO_EFFECT_COUNT; i++, effect++) {
+ if (!effect->alive) {
+ effect->alive = true;
+ effect->pos = *initPos;
+ effect->velocity = *initVelocity;
+ effect->accel = *accel;
+ effect->primColor = *primColor;
+ effect->alpha = 0;
+ effect->envColor = *envColor;
+ effect->scale = scale;
+ effect->timer = life;
+ effect->type = type;
+ effect->pitch = 0;
+ effect->yaw = TRUNCF_BINANG(Rand_CenteredFloat(30000.0f));
+ effect->roll = 0;
+ return;
+ }
+ }
+}
+
+void BgDyYoseizo_UpdateEffects(BgDyYoseizo* this, PlayState* play) {
+ BgDyYoseizoEffect* effect = this->effects;
+ Player* player = GET_PLAYER(play);
+ Vec3f sp94;
+ Vec3f sp88;
+ s32 pad[2];
+ f32 targetPitch;
+ f32 targetYaw;
+ f32 floatAngle;
+ s16 i = 0;
+
+ for (i = 0; i < BG_DY_YOSEIZO_EFFECT_COUNT; i++, effect++) {
+ if (effect->alive) {
+ effect->roll += 3000;
+
+ if (effect->type < GREAT_FAIRY_EFFECT_TRAJECTORY_CONVERGE_ON_PLAYER) {
+ effect->pos.x += effect->velocity.x;
+ effect->pos.y += effect->velocity.y;
+ effect->pos.z += effect->velocity.z;
+ effect->velocity.x += effect->accel.x;
+ effect->velocity.y += effect->accel.y;
+ effect->velocity.z += effect->accel.z;
+ } else {
+ Actor_PlaySfx(&this->actor, NA_SE_EV_HEALING - SFX_FLAG);
+
+ sp94 = player->actor.world.pos;
+ sp94.y = player->actor.world.pos.y - 150.0f;
+ sp94.z = player->actor.world.pos.z - 50.0f;
+
+ targetPitch = Math_Vec3f_Pitch(&effect->pos, &sp94);
+ targetYaw = Math_Vec3f_Yaw(&effect->pos, &sp94);
+
+ floatAngle = effect->pitch;
+ Math_ApproachF(&floatAngle, targetPitch, 0.9f, 5000.0f);
+ effect->pitch = floatAngle;
+
+ floatAngle = effect->yaw;
+ Math_ApproachF(&floatAngle, targetYaw, 0.9f, 5000.0f);
+ effect->yaw = floatAngle;
+
+ Matrix_Push();
+ Matrix_RotateYS(effect->yaw, MTXMODE_NEW);
+ Matrix_RotateXS(effect->pitch, MTXMODE_APPLY);
+
+ sp94.x = sp94.y = sp94.z = 3.0f;
+
+ Matrix_MultVec3f(&sp94, &sp88);
+ Matrix_Pop();
+ effect->pos.x += sp88.x;
+ effect->pos.y += sp88.y;
+ effect->pos.z += sp88.z;
+ }
+ }
+
+ // fade up, fade down, vanish and reset
+ if (effect->timer != 0) {
+ effect->timer--;
+ effect->alpha += 30;
+
+ if (effect->alpha > 255) {
+ effect->alpha = 255;
+ }
+ } else {
+ effect->alpha -= 30;
+
+ if (effect->alpha <= 0) {
+ effect->alpha = 0;
+ effect->alive = false;
+ }
+ }
+ }
+}
+
+void BgDyYoseizo_DrawEffects(BgDyYoseizo* this, PlayState* play) {
+ static f32 sStretchFactors[] = {
+ 1.0f, 1.1f, 1.15f, 1.1f, 1.0f, 0.9f, 0.85f, 0.9f,
+ };
+ GraphicsContext* gfxCtx = play->state.gfxCtx;
+ u8 setup = 0;
+ BgDyYoseizoEffect* effect = this->effects;
+ f32 stretchFactor = sStretchFactors[play->gameplayFrames % ARRAY_COUNT(sStretchFactors)];
+ s16 i;
+
+ OPEN_DISPS(gfxCtx);
+
+ Gfx_SetupDL25_Xlu(play->state.gfxCtx);
+
+ for (i = 0; i < BG_DY_YOSEIZO_EFFECT_COUNT; i++, effect++) {
+ if (effect->alive == true) {
+ if (setup == 0) {
+ gSPDisplayList(POLY_XLU_DISP++, gGreatFairyParticleSetupDL);
+ gDPPipeSync(POLY_XLU_DISP++);
+ setup++;
+ }
+
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, effect->primColor.r, effect->primColor.g, effect->primColor.b,
+ effect->alpha);
+ gDPSetEnvColor(POLY_XLU_DISP++, effect->envColor.r, effect->envColor.g, effect->envColor.b, 0);
+
+ Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
+ Matrix_ReplaceRotation(&play->billboardMtxF);
+
+ Matrix_Scale(effect->scale, effect->scale * stretchFactor, 1.0f, MTXMODE_APPLY);
+ Matrix_RotateZS(effect->roll, MTXMODE_APPLY);
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, gGreatFairyParticleDL);
+ }
+ }
+
+ CLOSE_DISPS(gfxCtx);
+}
diff --git a/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h b/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h
index bd06cdb384..4aaf67e778 100644
--- a/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h
+++ b/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h
@@ -2,15 +2,65 @@
#define Z_BG_DY_YOSEIZO_H
#include "global.h"
+#include "overlays/actors/ovl_En_Dy_Extra/z_en_dy_extra.h"
+#include "objects/object_dy_obj/object_dy_obj.h"
struct BgDyYoseizo;
typedef void (*BgDyYoseizoActionFunc)(struct BgDyYoseizo*, PlayState*);
+#define GREAT_FAIRY_GET_SWITCHFLAG(thisx) (((thisx)->params & 0xFE00) >> 9)
+#define GREAT_FAIRY_GET_TYPE(thisx) ((thisx)->params & 0xF)
+#define GREAT_FAIRY_ROTZ(thisx) ((thisx)->home.rot.z)
+
+typedef enum GreatFairyType {
+ /* 0 */ GREAT_FAIRY_TYPE_MAGIC,
+ /* 1 */ GREAT_FAIRY_TYPE_POWER,
+ /* 2 */ GREAT_FAIRY_TYPE_WISDOM,
+ /* 3 */ GREAT_FAIRY_TYPE_COURAGE,
+ /* 4 */ GREAT_FAIRY_TYPE_KINDNESS
+} GreatFairyType;
+
+#define BG_DY_YOSEIZO_EFFECT_COUNT 200
+
+typedef struct BgDyYoseizoEffect {
+ /* 0x00 */ u8 alive; // drawn if 1, respawn if 0
+ /* 0x04 */ Vec3f pos;
+ /* 0x10 */ Vec3f velocity;
+ /* 0x1C */ Vec3f accel;
+ /* 0x28 */ Color_RGB8 primColor;
+ /* 0x2B */ Color_RGB8 envColor;
+ /* 0x2E */ s16 alpha;
+ /* 0x30 */ f32 scale;
+ /* 0x34 */ s16 timer; // lifetime
+ /* 0x36 */ s16 type; // 0 is general radiance, else is directed towards Player
+ /* 0x38 */ s16 pitch;
+ /* 0x3A */ s16 yaw;
+ /* 0x3C */ s16 roll; // all three are f32 in OoT
+} BgDyYoseizoEffect; // size = 0x40
+
typedef struct BgDyYoseizo {
/* 0x0000 */ Actor actor;
/* 0x0144 */ BgDyYoseizoActionFunc actionFunc;
- /* 0x0148 */ char unk_148[0x33BC];
+ /* 0x0148 */ SkelAnime skelAnime;
+ /* 0x018C */ Vec3s jointTable[GREAT_FAIRY_LIMB_MAX];
+ /* 0x0234 */ Vec3s morphTable[GREAT_FAIRY_LIMB_MAX];
+ /* 0x02DC */ Vec3s headRot;
+ /* 0x02DC */ Vec3s torsoRot;
+ /* 0x02E8 */ EnDyExtra* beam;
+ /* 0x02EC */ f32 unk2EC; // unused
+ /* 0x02F0 */ f32 unk2F0;
+ /* 0x02F4 */ f32 unk2F4;
+ /* 0x02F8 */ union {
+ s16 unk2F8;
+ s16 csId; // used on BgDyYoseizo_TrainPlayer
+ };
+ /* 0x02FA */ s16 eyeIndex;
+ /* 0x02FC */ s16 mouthIndex;
+ /* 0x02FE */ s16 blinkTimer;
+ /* 0x0300 */ s16 timer;
+ /* 0x0302 */ u16 unk302;
+ /* 0x0304 */ BgDyYoseizoEffect effects[BG_DY_YOSEIZO_EFFECT_COUNT];
} BgDyYoseizo; // size = 0x3504
#endif // Z_BG_DY_YOSEIZO_H
diff --git a/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c
index ca472ccc30..ff88a61db0 100644
--- a/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c
+++ b/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c
@@ -16,14 +16,13 @@ void DemoEffect_Init(Actor* thisx, PlayState* play);
void DemoEffect_Destroy(Actor* thisx, PlayState* play);
void DemoEffect_Update(Actor* thisx, PlayState* play);
-void func_808CD940(DemoEffect* this, PlayState* play);
-void func_808CD998(DemoEffect* this, PlayState* play);
-void func_808CDBDC(DemoEffect* this, PlayState* play);
-void func_808CDCEC(DemoEffect* this, PlayState* play);
-void func_808CDD70(DemoEffect* this, PlayState* play);
-void func_808CDDE0(DemoEffect* this, PlayState* play);
-void func_808CDFF8(Actor* thisx, PlayState* play);
-void func_808CE078(Actor* thisx, PlayState* play2);
+void DemoEffect_WaitForObject(DemoEffect* this, PlayState* play);
+void DemoEffect_SetupTimewarp(DemoEffect* this, PlayState* play);
+void DemoEffect_StartTimewarp(DemoEffect* this, PlayState* play);
+void DemoEffect_ShrinkLight(DemoEffect* this, PlayState* play);
+void DemoEffect_ExpandLight(DemoEffect* this, PlayState* play);
+void DemoEffect_DrawTimewarp(Actor* thisx, PlayState* play);
+void DemoEffect_DrawLight(Actor* thisx, PlayState* play2);
ActorInit Demo_Effect_InitVars = {
ACTOR_DEMO_EFFECT,
@@ -47,8 +46,12 @@ void DemoEffect_Init(Actor* thisx, PlayState* play) {
s32 type = DEMO_EFFECT_GET_TYPE(&this->actor);
s32 objectIndex;
s32 pad2;
- Color_RGB8 colors[] = {
- { 200, 200, 0 }, { 255, 40, 100 }, { 50, 255, 0 }, { 0, 0, 255 }, { 255, 255, 80 },
+ Color_RGB8 lightColors[] = {
+ { 200, 200, 0 }, // Yellow
+ { 255, 40, 100 }, // Pink
+ { 50, 255, 0 }, // Light green
+ { 0, 0, 255 }, // Blue
+ { 255, 255, 80 }, // Light Yellow
};
if (sEffectTypeObjects[type] == GAMEPLAY_KEEP) {
@@ -66,14 +69,14 @@ void DemoEffect_Init(Actor* thisx, PlayState* play) {
Actor_SetScale(&this->actor, 0.2f);
switch (type) {
- case DEMO_EFFECT_TYPE_0:
- case DEMO_EFFECT_TYPE_1:
+ case DEMO_EFFECT_TIMEWARP_TIMEBLOCK_LARGE:
+ case DEMO_EFFECT_TIMEWARP_TIMEBLOCK_SMALL:
this->actor.flags |= ACTOR_FLAG_2000000;
-
- case DEMO_EFFECT_TYPE_2:
- case DEMO_EFFECT_TYPE_3:
- this->initDrawFunc = func_808CDFF8;
- this->initActionFunc = func_808CD998;
+ // FALLTHROUGH
+ case DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_LARGE:
+ case DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_VERY_LARGE:
+ this->initDrawFunc = DemoEffect_DrawTimewarp;
+ this->initActionFunc = DemoEffect_SetupTimewarp;
this->envXluColor[0] = 0;
this->envXluColor[1] = 100;
this->envXluColor[2] = 255;
@@ -81,17 +84,17 @@ void DemoEffect_Init(Actor* thisx, PlayState* play) {
this->timer = 0;
break;
- case DEMO_EFFECT_TYPE_4:
- case DEMO_EFFECT_TYPE_5:
- case DEMO_EFFECT_TYPE_6:
- case DEMO_EFFECT_TYPE_7:
- case DEMO_EFFECT_TYPE_8:
- this->envXluColor[0] = colors[type - 4].r;
- this->envXluColor[1] = colors[type - 4].g;
- this->envXluColor[2] = colors[type - 4].b;
+ case DEMO_EFFECT_TYPE_LIGHT_DARK_YELLOW:
+ case DEMO_EFFECT_TYPE_LIGHT_PINK:
+ case DEMO_EFFECT_TYPE_LIGHT_GREEN:
+ case DEMO_EFFECT_TYPE_LIGHT_BLUE:
+ case DEMO_EFFECT_TYPE_LIGHT_YELLOW:
+ this->envXluColor[0] = lightColors[type - DEMO_EFFECT_TYPE_LIGHT_BASE].r;
+ this->envXluColor[1] = lightColors[type - DEMO_EFFECT_TYPE_LIGHT_BASE].g;
+ this->envXluColor[2] = lightColors[type - DEMO_EFFECT_TYPE_LIGHT_BASE].b;
Actor_SetScale(&this->actor, 0.0f);
- this->initDrawFunc = func_808CE078;
- this->initActionFunc = func_808CDDE0;
+ this->initDrawFunc = DemoEffect_DrawLight;
+ this->initActionFunc = DemoEffect_ExpandLight;
this->timer = 0;
break;
@@ -100,17 +103,17 @@ void DemoEffect_Init(Actor* thisx, PlayState* play) {
}
ActorShape_Init(&this->actor.shape, 0.0f, NULL, 0.0f);
- this->actionFunc = func_808CD940;
+ this->actionFunc = DemoEffect_WaitForObject;
}
void DemoEffect_Destroy(Actor* thisx, PlayState* play) {
DemoEffect* this = THIS;
switch (DEMO_EFFECT_GET_TYPE(&this->actor)) {
- case DEMO_EFFECT_TYPE_0:
- case DEMO_EFFECT_TYPE_1:
- case DEMO_EFFECT_TYPE_2:
- case DEMO_EFFECT_TYPE_3:
+ case DEMO_EFFECT_TIMEWARP_TIMEBLOCK_LARGE:
+ case DEMO_EFFECT_TIMEWARP_TIMEBLOCK_SMALL:
+ case DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_LARGE:
+ case DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_VERY_LARGE:
SkelCurve_Destroy(play, &this->skelCurve);
break;
@@ -119,7 +122,7 @@ void DemoEffect_Destroy(Actor* thisx, PlayState* play) {
}
}
-void func_808CD940(DemoEffect* this, PlayState* play) {
+void DemoEffect_WaitForObject(DemoEffect* this, PlayState* play) {
if (Object_IsLoaded(&play->objectCtx, this->initObjectIndex)) {
this->actor.objBankIndex = this->initObjectIndex;
this->actor.draw = this->initDrawFunc;
@@ -127,41 +130,41 @@ void func_808CD940(DemoEffect* this, PlayState* play) {
}
}
-void func_808CD998(DemoEffect* this, PlayState* play) {
+void DemoEffect_SetupTimewarp(DemoEffect* this, PlayState* play) {
s32 type = DEMO_EFFECT_GET_TYPE(&this->actor);
- if (SkelCurve_Init(play, &this->skelCurve, &object_efc_tw_Skel_0012E8, &object_efc_tw_CurveAnim_000050)) {}
+ if (SkelCurve_Init(play, &this->skelCurve, &gTimewarpSkel, &gTimewarpAnim)) {}
- SkelCurve_SetAnim(&this->skelCurve, &object_efc_tw_CurveAnim_000050, 1.0f, 59.0f, 1.0f, 1.7f);
+ SkelCurve_SetAnim(&this->skelCurve, &gTimewarpAnim, 1.0f, 59.0f, 1.0f, 1.7f);
SkelCurve_Update(play, &this->skelCurve);
- this->actionFunc = func_808CDCEC;
+ this->actionFunc = DemoEffect_StartTimewarp;
switch (type) {
- case DEMO_EFFECT_TYPE_0:
- Actor_SetScale(&this->actor, 0.16800001f);
+ case DEMO_EFFECT_TIMEWARP_TIMEBLOCK_LARGE:
+ Actor_SetScale(&this->actor, 168.0f * 0.001f);
break;
- case DEMO_EFFECT_TYPE_1:
- Actor_SetScale(&this->actor, 0.08400001f);
+ case DEMO_EFFECT_TIMEWARP_TIMEBLOCK_SMALL:
+ Actor_SetScale(&this->actor, 84.0f * 0.001f);
break;
- case DEMO_EFFECT_TYPE_2:
- Actor_SetScale(&this->actor, 0.16800001f);
+ case DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_LARGE:
+ Actor_SetScale(&this->actor, 168.0f * 0.001f);
break;
- case DEMO_EFFECT_TYPE_3:
- Actor_SetScale(&this->actor, 0.28f);
+ case DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_VERY_LARGE:
+ Actor_SetScale(&this->actor, 280.0f * 0.001f);
break;
default:
- Actor_SetScale(&this->actor, 0.014f);
+ Actor_SetScale(&this->actor, 14.0f * 0.001f);
break;
}
}
-void func_808CDAD0(f32 alphaScale) {
+void DemoEffect_SetPerVertexAlpha(f32 alphaScale) {
static u8 sAlphaTypes[] = { 1, 1, 2, 0, 1, 1, 2, 0, 1, 2, 0, 2, 1, 0, 1, 0, 2, 0, 2, 2, 0 };
- Vtx* vtx = Lib_SegmentedToVirtual(object_efc_tw_Vtx_000060);
+ Vtx* vtx = Lib_SegmentedToVirtual(gTimewarpVtx);
s32 i;
u8 alphas[3];
@@ -176,7 +179,10 @@ void func_808CDAD0(f32 alphaScale) {
}
}
-void func_808CDBDC(DemoEffect* this, PlayState* play) {
+/**
+ * Shrink and fade linearly for 100 frames then remove.
+ */
+void DemoEffect_FinishTimewarp(DemoEffect* this, PlayState* play) {
s32 type = DEMO_EFFECT_GET_TYPE(&this->actor);
f32 scale;
f32 alphaScale;
@@ -187,19 +193,19 @@ void func_808CDBDC(DemoEffect* this, PlayState* play) {
scale = alphaScale * 0.14f;
switch (type) {
- case DEMO_EFFECT_TYPE_0:
+ case DEMO_EFFECT_TIMEWARP_TIMEBLOCK_LARGE:
scale *= 1.2f;
break;
- case DEMO_EFFECT_TYPE_1:
+ case DEMO_EFFECT_TIMEWARP_TIMEBLOCK_SMALL:
scale *= 0.6f;
break;
- case DEMO_EFFECT_TYPE_2:
+ case DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_LARGE:
scale *= 1.2f;
break;
- case DEMO_EFFECT_TYPE_3:
+ case DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_VERY_LARGE:
scale *= 2.0f;
break;
@@ -209,25 +215,31 @@ void func_808CDBDC(DemoEffect* this, PlayState* play) {
this->actor.scale.x = scale;
this->actor.scale.z = scale;
- func_808CDAD0(alphaScale);
+ DemoEffect_SetPerVertexAlpha(alphaScale);
Actor_PlaySfx_FlaggedCentered3(&this->actor, NA_SE_EV_TIMETRIP_LIGHT - SFX_FLAG);
} else {
- func_808CDAD0(1.0f);
+ DemoEffect_SetPerVertexAlpha(1.0f);
Actor_Kill(&this->actor);
}
}
-void func_808CDCEC(DemoEffect* this, PlayState* play) {
+/**
+ * Runs until animation plays to frame 59 and pauses it on frame 59.
+ */
+void DemoEffect_StartTimewarp(DemoEffect* this, PlayState* play) {
Actor_PlaySfx_FlaggedCentered3(&this->actor, NA_SE_EV_TIMETRIP_LIGHT - SFX_FLAG);
if (SkelCurve_Update(play, &this->skelCurve)) {
- SkelCurve_SetAnim(&this->skelCurve, &object_efc_tw_CurveAnim_000050, 1.0f, 60.0f, 59.0f, 0.0f);
- this->actionFunc = func_808CDBDC;
+ SkelCurve_SetAnim(&this->skelCurve, &gTimewarpAnim, 1.0f, 60.0f, 59.0f, 0.0f);
+ this->actionFunc = DemoEffect_FinishTimewarp;
this->timer = 0;
}
}
-void func_808CDD70(DemoEffect* this, PlayState* play) {
+/**
+ * Take scale to 0 linearly, when scale is small enough, remove.
+ */
+void DemoEffect_ShrinkLight(DemoEffect* this, PlayState* play) {
Actor_SetScale(&this->actor, this->actor.scale.x - 0.02f);
this->timer++;
@@ -236,12 +248,16 @@ void func_808CDD70(DemoEffect* this, PlayState* play) {
}
}
-void func_808CDDE0(DemoEffect* this, PlayState* play) {
+/**
+ * Changes scale for 3 frames, scale is successively 0.0f, 0.2f, 0.3f, 0.35f (would converge to 0.4 exponentially if run
+ * for a long time).
+ */
+void DemoEffect_ExpandLight(DemoEffect* this, PlayState* play) {
Actor_SetScale(&this->actor, (this->actor.scale.x * 0.5f) + 0.2f);
this->timer++;
if (this->timer >= 3) {
- this->actionFunc = func_808CDD70;
+ this->actionFunc = DemoEffect_ShrinkLight;
}
}
@@ -251,7 +267,7 @@ void DemoEffect_Update(Actor* thisx, PlayState* play) {
this->actionFunc(this, play);
}
-s32 func_808CDE78(PlayState* play, SkelCurve* skelCurve, s32 limbIndex, Actor* thisx) {
+s32 DemoEffect_OverrideLimbDrawTimewarp(PlayState* play, SkelCurve* skelCurve, s32 limbIndex, Actor* thisx) {
s32 pad;
DemoEffect* this = THIS;
u32 frames = play->gameplayFrames;
@@ -278,7 +294,7 @@ s32 func_808CDE78(PlayState* play, SkelCurve* skelCurve, s32 limbIndex, Actor* t
return true;
}
-void func_808CDFF8(Actor* thisx, PlayState* play) {
+void DemoEffect_DrawTimewarp(Actor* thisx, PlayState* play) {
GraphicsContext* gfxCtx = play->state.gfxCtx;
DemoEffect* this = THIS;
@@ -287,12 +303,12 @@ void func_808CDFF8(Actor* thisx, PlayState* play) {
POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, SETUPDL_25);
Matrix_Scale(2.0f, 2.0f, 2.0f, MTXMODE_APPLY);
- SkelCurve_Draw(&this->actor, play, &this->skelCurve, func_808CDE78, NULL, 1, &this->actor);
+ SkelCurve_Draw(&this->actor, play, &this->skelCurve, DemoEffect_OverrideLimbDrawTimewarp, NULL, 1, &this->actor);
CLOSE_DISPS(gfxCtx);
}
-void func_808CE078(Actor* thisx, PlayState* play2) {
+void DemoEffect_DrawLight(Actor* thisx, PlayState* play2) {
PlayState* play = play2;
DemoEffect* this = THIS;
s16 zRot = (this->timer * 0x400) & 0xFFFF;
diff --git a/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.h b/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.h
index 9901a31898..a693163082 100644
--- a/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.h
+++ b/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.h
@@ -11,15 +11,16 @@ typedef void (*DemoEffectActionFunc)(struct DemoEffect*, PlayState*);
#define DEMO_EFFECT_GET_TYPE(thisx) ((thisx)->params & 0xFF)
typedef enum {
- /* 0 */ DEMO_EFFECT_TYPE_0,
- /* 1 */ DEMO_EFFECT_TYPE_1,
- /* 2 */ DEMO_EFFECT_TYPE_2,
- /* 3 */ DEMO_EFFECT_TYPE_3,
- /* 4 */ DEMO_EFFECT_TYPE_4,
- /* 5 */ DEMO_EFFECT_TYPE_5,
- /* 6 */ DEMO_EFFECT_TYPE_6,
- /* 7 */ DEMO_EFFECT_TYPE_7,
- /* 8 */ DEMO_EFFECT_TYPE_8
+ /* 0 */ DEMO_EFFECT_TIMEWARP_TIMEBLOCK_LARGE,
+ /* 1 */ DEMO_EFFECT_TIMEWARP_TIMEBLOCK_SMALL,
+ /* 2 */ DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_LARGE,
+ /* 3 */ DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_VERY_LARGE,
+ /* 4 */ DEMO_EFFECT_TYPE_LIGHT_BASE,
+ /* 4 */ DEMO_EFFECT_TYPE_LIGHT_DARK_YELLOW = DEMO_EFFECT_TYPE_LIGHT_BASE,
+ /* 5 */ DEMO_EFFECT_TYPE_LIGHT_PINK,
+ /* 6 */ DEMO_EFFECT_TYPE_LIGHT_GREEN,
+ /* 7 */ DEMO_EFFECT_TYPE_LIGHT_BLUE,
+ /* 8 */ DEMO_EFFECT_TYPE_LIGHT_YELLOW // Unused
} DemoEffectType;
typedef struct DemoEffect {
diff --git a/src/overlays/actors/ovl_Demo_Getitem/z_demo_getitem.c b/src/overlays/actors/ovl_Demo_Getitem/z_demo_getitem.c
index 6882c189a2..63228436f6 100644
--- a/src/overlays/actors/ovl_Demo_Getitem/z_demo_getitem.c
+++ b/src/overlays/actors/ovl_Demo_Getitem/z_demo_getitem.c
@@ -1,7 +1,7 @@
/*
* File: z_demo_getitem.c
* Overlay: ovl_Demo_Getitem
- * Description: Cutscene objectIndex for Great Fairy's Mask and Great Fairy's Sword
+ * Description: Cutscene objects for Great Fairy's Mask and Great Fairy's Sword
*/
#include "z_demo_getitem.h"
@@ -14,8 +14,8 @@ void DemoGetitem_Init(Actor* thisx, PlayState* play);
void DemoGetitem_Destroy(Actor* thisx, PlayState* play);
void DemoGetitem_Update(Actor* thisx, PlayState* play);
-void func_80A4FB10(DemoGetitem* this, PlayState* play);
-void func_80A4FB68(DemoGetitem* this, PlayState* play2);
+void DemoGetitem_Wait(DemoGetitem* this, PlayState* play);
+void DemoGetitem_PerformCutsceneActions(DemoGetitem* this, PlayState* play);
void DemoGetitem_Draw(Actor* thisx, PlayState* play);
ActorInit Demo_Getitem_InitVars = {
@@ -36,20 +36,27 @@ static s16 sGetItemDraws[] = { GID_MASK_GREAT_FAIRY, GID_SWORD_GREAT_FAIRY };
static u16 sCueTypes[] = { CS_CMD_ACTOR_CUE_110, CS_CMD_ACTOR_CUE_566 };
+typedef enum GreatFairyRewardItem {
+ /* 0 */ DEMOGETITEM_ITEM_MASK_GREAT_FAIRY,
+ /* 1 */ DEMOGETITEM_ITEM_SWORD_GREAT_FAIRY
+} GreatFairyRewardItem;
+
void DemoGetitem_Init(Actor* thisx, PlayState* play) {
s32 pad;
s32 objectIndex;
s32 itemIndex;
DemoGetitem* this = THIS;
- itemIndex = 0;
- if (DEMOGETITEM_GET_F(thisx) == 1) {
- itemIndex = 1;
+ itemIndex = DEMOGETITEM_ITEM_MASK_GREAT_FAIRY;
+ if (DEMOGETITEM_GET_F(&this->actor) == 1) {
+ itemIndex = DEMOGETITEM_ITEM_SWORD_GREAT_FAIRY;
}
+
Actor_SetScale(&this->actor, 0.25f);
- this->actionFunc = func_80A4FB10;
- this->item = sGetItemDraws[itemIndex];
+ this->actionFunc = DemoGetitem_Wait;
+ this->getItemDrawId = sGetItemDraws[itemIndex];
this->cueType = sCueTypes[itemIndex];
+
objectIndex = Object_GetIndex(&play->objectCtx, sObjectBankIndices[itemIndex]);
if (objectIndex < 0) {
Actor_Kill(&this->actor);
@@ -62,22 +69,23 @@ void DemoGetitem_Init(Actor* thisx, PlayState* play) {
void DemoGetitem_Destroy(Actor* thisx, PlayState* play) {
}
-void func_80A4FB10(DemoGetitem* this, PlayState* play) {
+void DemoGetitem_Wait(DemoGetitem* this, PlayState* play) {
if (Object_IsLoaded(&play->objectCtx, this->objectIndex)) {
this->actor.draw = NULL;
this->actor.objBankIndex = this->objectIndex;
- this->actionFunc = func_80A4FB68;
+ this->actionFunc = DemoGetitem_PerformCutsceneActions;
}
}
-void func_80A4FB68(DemoGetitem* this, PlayState* play2) {
- PlayState* play = play2;
- u16 sp22 = (play->gameplayFrames * 1000) & 0xFFFF;
+void DemoGetitem_PerformCutsceneActions(DemoGetitem* this, PlayState* play) {
+ s32 pad;
+ u16 bobPhase = (play->gameplayFrames * 1000) % 0x10000;
if (Cutscene_IsCueInChannel(play, this->cueType)) {
if (play->csCtx.actorCues[Cutscene_GetCueChannel(play, this->cueType)]->id != 4) {
this->actor.shape.yOffset = 0.0f;
}
+
switch (play->csCtx.actorCues[Cutscene_GetCueChannel(play, this->cueType)]->id) {
case 2:
this->actor.draw = DemoGetitem_Draw;
@@ -92,7 +100,7 @@ void func_80A4FB68(DemoGetitem* this, PlayState* play2) {
case 4:
this->actor.draw = DemoGetitem_Draw;
Cutscene_ActorTranslateAndYaw(&this->actor, play, Cutscene_GetCueChannel(play, this->cueType));
- this->actor.shape.yOffset = Math_SinS(sp22) * 15.0f;
+ this->actor.shape.yOffset = Math_SinS(bobPhase) * 15.0f;
break;
default:
@@ -115,5 +123,5 @@ void DemoGetitem_Draw(Actor* thisx, PlayState* play) {
func_800B8050(&this->actor, play, 0);
func_800B8118(&this->actor, play, 0);
- GetItem_Draw(play, this->item);
+ GetItem_Draw(play, this->getItemDrawId);
}
diff --git a/src/overlays/actors/ovl_Demo_Getitem/z_demo_getitem.h b/src/overlays/actors/ovl_Demo_Getitem/z_demo_getitem.h
index ca00f60484..130b2cfa64 100644
--- a/src/overlays/actors/ovl_Demo_Getitem/z_demo_getitem.h
+++ b/src/overlays/actors/ovl_Demo_Getitem/z_demo_getitem.h
@@ -11,7 +11,7 @@ typedef void (*DemoGetitemActionFunc)(struct DemoGetitem*, PlayState*);
typedef struct DemoGetitem {
/* 0x000 */ Actor actor;
- /* 0x144 */ s16 item;
+ /* 0x144 */ s16 getItemDrawId;
/* 0x146 */ u16 cueType;
/* 0x148 */ s8 objectIndex;
/* 0x14C */ DemoGetitemActionFunc actionFunc;
diff --git a/src/overlays/actors/ovl_En_Box/z_en_box.c b/src/overlays/actors/ovl_En_Box/z_en_box.c
index 959a986a41..8157d09c6b 100644
--- a/src/overlays/actors/ovl_En_Box/z_en_box.c
+++ b/src/overlays/actors/ovl_En_Box/z_en_box.c
@@ -539,7 +539,8 @@ void EnBox_Open(EnBox* this, PlayState* play) {
Actor_SpawnAsChild(&play->actorCtx, &this->dyna.actor, play, ACTOR_EN_ELFORG, this->dyna.actor.world.pos.x,
this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, this->dyna.actor.world.rot.x,
this->dyna.actor.world.rot.y, this->dyna.actor.world.rot.z,
- STRAY_FAIRY_PARAMS(ENBOX_GET_CHEST_FLAG(&this->dyna.actor), 0, STRAY_FAIRY_TYPE_CHEST));
+ STRAY_FAIRY_PARAMS(ENBOX_GET_CHEST_FLAG(&this->dyna.actor), STRAY_FAIRY_AREA_CLOCK_TOWN,
+ STRAY_FAIRY_TYPE_CHEST));
} else if (this->movementFlags & ENBOX_MOVE_0x40) {
this->movementFlags &= ~ENBOX_MOVE_0x40;
}
diff --git a/src/overlays/actors/ovl_En_Dy_Extra/z_en_dy_extra.c b/src/overlays/actors/ovl_En_Dy_Extra/z_en_dy_extra.c
index 14f08c5319..b8dea95a07 100644
--- a/src/overlays/actors/ovl_En_Dy_Extra/z_en_dy_extra.c
+++ b/src/overlays/actors/ovl_En_Dy_Extra/z_en_dy_extra.c
@@ -16,8 +16,8 @@ void EnDyExtra_Destroy(Actor* thisx, PlayState* play);
void EnDyExtra_Update(Actor* thisx, PlayState* play);
void EnDyExtra_Draw(Actor* thisx, PlayState* play);
-void func_80A61334(EnDyExtra* this, PlayState* play);
-void func_80A613C8(EnDyExtra* this, PlayState* play);
+void EnDyExtra_WaitForTrigger(EnDyExtra* this, PlayState* play);
+void EnDyExtra_Fall(EnDyExtra* this, PlayState* play);
ActorInit En_Dy_Extra_InitVars = {
ACTOR_EN_DY_EXTRA,
@@ -41,35 +41,35 @@ void EnDyExtra_Init(Actor* thisx, PlayState* play) {
this->actor.scale.x = 0.025f;
this->actor.scale.y = 0.039f;
this->actor.scale.z = 0.025f;
- this->unk160 = this->actor.world.pos;
+ this->initPos = this->actor.world.pos;
this->actor.gravity = -0.2f;
- this->unk150 = 1.0f;
- this->unk14C = 0x3C;
- this->actionFunc = func_80A61334;
+ this->alphaScale = 1.0f;
+ this->timer = 60;
+ this->actionFunc = EnDyExtra_WaitForTrigger;
}
-void func_80A61334(EnDyExtra* this, PlayState* play) {
+void EnDyExtra_WaitForTrigger(EnDyExtra* this, PlayState* play) {
Math_ApproachF(&this->actor.gravity, 0.0f, 0.1f, 0.005f);
if (this->actor.world.pos.y < -85.0f) {
this->actor.velocity.y = 0.0f;
}
- if ((this->unk14C == 0) && (this->unk14A != 0)) {
- this->unk14C = 0x32;
- this->actionFunc = func_80A613C8;
+ if ((this->timer == 0) && this->trigger) {
+ this->timer = 50;
+ this->actionFunc = EnDyExtra_Fall;
}
}
-void func_80A613C8(EnDyExtra* this, PlayState* play) {
+void EnDyExtra_Fall(EnDyExtra* this, PlayState* play) {
Math_ApproachF(&this->actor.gravity, 0.0f, 0.1f, 0.005f);
- if ((this->unk14C == 0) || (this->unk150 < 0.02f)) {
+ if ((this->timer == 0) || (this->alphaScale < 0.02f)) {
Actor_Kill(&this->actor);
return;
}
- this->unk150 -= 0.02f;
+ this->alphaScale -= 0.02f;
if (this->actor.world.pos.y < -85.0f) {
this->actor.velocity.y = 0.0f;
@@ -79,40 +79,40 @@ void func_80A613C8(EnDyExtra* this, PlayState* play) {
void EnDyExtra_Update(Actor* thisx, PlayState* play) {
EnDyExtra* this = THIS;
- DECR(this->unk14C);
+ DECR(this->timer);
Actor_PlaySfx(&this->actor, NA_SE_PL_SPIRAL_HEAL_BEAM - SFX_FLAG);
this->actionFunc(this, play);
Actor_MoveWithGravity(&this->actor);
}
-static Color_RGBA8 D_80A61740[] = {
+static Color_RGBA8 sPrimColors[] = {
{ 255, 255, 170, 255 }, { 255, 170, 255, 255 }, { 255, 255, 170, 255 },
{ 170, 255, 255, 255 }, { 255, 255, 170, 255 },
};
-static Color_RGBA8 D_80A61754[] = {
+static Color_RGBA8 sEnvColors[] = {
{ 255, 100, 0, 255 }, { 255, 0, 100, 255 }, { 100, 255, 0, 255 }, { 0, 100, 255, 255 }, { 255, 230, 0, 255 }
};
-static u8 D_80A61768[] = {
- 2, 1, 1, 2, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 2, 0, 0,
+static u8 sAlphaTypeIndices[] = {
+ 2, 1, 1, 2, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 2, 0,
};
void EnDyExtra_Draw(Actor* thisx, PlayState* play) {
- EnDyExtra* this = THIS;
s32 pad;
+ EnDyExtra* this = THIS;
GraphicsContext* gfxCtx = play->state.gfxCtx;
- Vtx* vertices = Lib_SegmentedToVirtual(object_dy_obj_Vtx_00DD40);
+ Vtx* vertices = Lib_SegmentedToVirtual(gGreatFairySpiralBeamVtx);
s32 i;
- u8 unk[3];
+ u8 alphas[3];
- unk[0] = 0.0f;
- unk[1] = (s8)(this->unk150 * 240.0f);
- unk[2] = (s8)(this->unk150 * 255.0f);
+ alphas[0] = 0.0f;
+ alphas[1] = (s32)(this->alphaScale * 240.0f);
+ alphas[2] = (s32)(this->alphaScale * 255.0f);
- for (i = 0; i < 27; i++) {
- if (D_80A61768[i]) {
- vertices[i].v.cn[3] = unk[D_80A61768[i]];
+ for (i = 0; i < ARRAY_COUNT(sAlphaTypeIndices); i++) {
+ if (sAlphaTypeIndices[i]) {
+ vertices[i].v.cn[3] = alphas[sAlphaTypeIndices[i]];
}
}
@@ -124,10 +124,10 @@ void EnDyExtra_Draw(Actor* thisx, PlayState* play) {
play->state.frames * -8, 0x10, 0x10));
gDPPipeSync(POLY_XLU_DISP++);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, D_80A61740[this->type].r, D_80A61740[this->type].g,
- D_80A61740[this->type].b, 255);
- gDPSetEnvColor(POLY_XLU_DISP++, D_80A61754[this->type].r, D_80A61754[this->type].g, D_80A61754[this->type].b, 128);
- gSPDisplayList(POLY_XLU_DISP++, object_dy_obj_DL_00DEF0);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, sPrimColors[this->type].r, sPrimColors[this->type].g,
+ sPrimColors[this->type].b, 255);
+ gDPSetEnvColor(POLY_XLU_DISP++, sEnvColors[this->type].r, sEnvColors[this->type].g, sEnvColors[this->type].b, 128);
+ gSPDisplayList(POLY_XLU_DISP++, gGreatFairySpiralBeamDL);
CLOSE_DISPS(gfxCtx);
}
diff --git a/src/overlays/actors/ovl_En_Dy_Extra/z_en_dy_extra.h b/src/overlays/actors/ovl_En_Dy_Extra/z_en_dy_extra.h
index 0e5d8614b7..f36b12051e 100644
--- a/src/overlays/actors/ovl_En_Dy_Extra/z_en_dy_extra.h
+++ b/src/overlays/actors/ovl_En_Dy_Extra/z_en_dy_extra.h
@@ -11,12 +11,11 @@ typedef struct EnDyExtra {
/* 0x000 */ Actor actor;
/* 0x144 */ EnDyExtraActionFunc actionFunc;
/* 0x148 */ s16 type;
- /* 0x14A */ s16 unk14A;
- /* 0x14C */ s16 unk14C;
- /* 0x14E */ s16 unk14E;
- /* 0x150 */ f32 unk150;
- /* 0x154 */ UNK_TYPE1 unk154[0xC];
- /* 0x160 */ Vec3f unk160;
+ /* 0x14A */ s16 trigger;
+ /* 0x14C */ s16 timer;
+ /* 0x150 */ f32 alphaScale;
+ /* 0x154 */ Vec3f scale; // not used, leftover from OoT
+ /* 0x160 */ Vec3f initPos; // set and not used
} EnDyExtra; // size = 0x16C
#endif // Z_EN_DY_EXTRA_H
diff --git a/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/src/overlays/actors/ovl_En_Elf/z_en_elf.c
index 61cf693d7d..f1526d66b8 100644
--- a/src/overlays/actors/ovl_En_Elf/z_en_elf.c
+++ b/src/overlays/actors/ovl_En_Elf/z_en_elf.c
@@ -744,7 +744,7 @@ void func_8088E0F0(EnElf* this, PlayState* play) {
if (this->unk_250 < 2.0f) {
this->unk_250 += 0.1f;
} else {
- gSaveContext.healthAccumulator = 160;
+ gSaveContext.healthAccumulator = 0xA0;
this->unk_246++;
}
break;
diff --git a/src/overlays/actors/ovl_En_Elfbub/z_en_elfbub.c b/src/overlays/actors/ovl_En_Elfbub/z_en_elfbub.c
index ef53999de0..9b34bf410e 100644
--- a/src/overlays/actors/ovl_En_Elfbub/z_en_elfbub.c
+++ b/src/overlays/actors/ovl_En_Elfbub/z_en_elfbub.c
@@ -73,10 +73,11 @@ void EnElfbub_Init(Actor* thisx, PlayState* play) {
Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
- childActor = Actor_SpawnAsChild(
- &play->actorCtx, &this->actor, play, ACTOR_EN_ELFORG, this->actor.world.pos.x, this->actor.world.pos.y + 12.0f,
- this->actor.world.pos.z, this->actor.world.rot.x, this->actor.world.rot.y, this->actor.world.rot.z,
- STRAY_FAIRY_PARAMS(ENELFBUB_GET_SWITCHFLAG(&this->actor), 0, STRAY_FAIRY_TYPE_BUBBLE));
+ childActor = Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_ELFORG, this->actor.world.pos.x,
+ this->actor.world.pos.y + 12.0f, this->actor.world.pos.z, this->actor.world.rot.x,
+ this->actor.world.rot.y, this->actor.world.rot.z,
+ STRAY_FAIRY_PARAMS(ENELFBUB_GET_SWITCHFLAG(&this->actor),
+ STRAY_FAIRY_AREA_CLOCK_TOWN, STRAY_FAIRY_TYPE_BUBBLE));
if (childActor != NULL) {
childActor->parent = &this->actor;
}
@@ -140,6 +141,7 @@ void EnElfbub_Idle(EnElfbub* this, PlayState* play) {
void EnElfbub_Update(Actor* thisx, PlayState* play) {
EnElfbub* this = THIS;
+
Collider_UpdateCylinder(&this->actor, &this->collider);
this->actionFunc(this, play);
Actor_SetFocus(&this->actor, this->actor.shape.yOffset);
diff --git a/src/overlays/actors/ovl_En_Elfgrp/z_en_elfgrp.c b/src/overlays/actors/ovl_En_Elfgrp/z_en_elfgrp.c
index 42ac47f699..937c6bc8ca 100644
--- a/src/overlays/actors/ovl_En_Elfgrp/z_en_elfgrp.c
+++ b/src/overlays/actors/ovl_En_Elfgrp/z_en_elfgrp.c
@@ -1,11 +1,38 @@
-/*
- * File: z_en_elfgrp.c
+/**
+ * @file z_en_elfgrp.c
* Overlay: ovl_En_Elfgrp
- * Description: Group of Stray Fairies in Fairy Fountain
+ * Description: Manager for group of Stray Fairies and Great Fairy in Fairy's Fountains
+ *
+ * There are many different quantities associated to the Stray Fairies in each of the 3 places (missing, in the
+ * Fountain, held by Player)
+ * - Total number of fairies (always 25 in the original game)
+ * - Original number in the Fountain (24 for Clock Town Fairy Fountain, 10 for the other 4)
+ * - Current number in the Fountain (bitpacked in Fountain scene flags, see below)
+ * - Total number found (stored in save context)
+ * - Current number held (i.e. found but not returned)
+ *
+ * The permanentSceneFlags for Fairy Fountains used in this actor are of the form
+ * ```c
+ * struct {
+ * u32 clockTown : 1;
+ * u32 fountains[4] : 5;
+ * } FairyFountains;
+ * ```
+ * where arg1 is:
+ * - 0: Clock Town
+ * - 1: Woodfall,
+ * - 2: Snowhead,
+ * - 3: Great Bay,
+ * - 4: Ikana
+ *
+ * Clock Town is handled separately, and then the fountains are looked up with manual array indexing
+ *
+ * @note Clock Town is handled separately in a number of places
*/
#include "z_en_elfgrp.h"
#include "overlays/actors/ovl_En_Elforg/z_en_elforg.h"
+#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
#define FLAGS (ACTOR_FLAG_10)
@@ -17,24 +44,28 @@ void EnElfgrp_Init(Actor* thisx, PlayState* play);
void EnElfgrp_Destroy(Actor* thisx, PlayState* play);
void EnElfgrp_Update(Actor* thisx, PlayState* play);
-s32 func_80A39BD0(PlayState* play, s32 arg2);
-s32 func_80A39C1C(PlayState* play, s32 arg1);
-void func_80A39DC8(EnElfgrp* this, PlayState* play, s32 arg2, s32 arg3);
-void func_80A3A0AC(EnElfgrp* this, PlayState* play);
-void func_80A3A0F4(EnElfgrp* this, PlayState* play);
-void func_80A3A210(EnElfgrp* this, PlayState* play);
-void func_80A3A274(EnElfgrp* this, PlayState* play);
+s32 EnElfgrp_GetHeldFairiesCount(PlayState* play, s32 type);
+s32 EnElfgrp_GetFountainFairiesCount(PlayState* play, s32 type);
+void EnElfgrp_SpawnStrayFairies(EnElfgrp* this, PlayState* play, s32 count, s32 fairyType);
void func_80A3A398(EnElfgrp* this, PlayState* play);
-void func_80A3A484(EnElfgrp* this, PlayState* play);
-void func_80A3A4AC(EnElfgrp* this, PlayState* play);
void func_80A3A520(EnElfgrp* this, PlayState* play);
-void func_80A3A600(EnElfgrp* this, PlayState* play);
-void func_80A3A610(EnElfgrp* this, PlayState* play);
-void func_80A3A6F4(EnElfgrp* this, PlayState* play);
-void func_80A3A77C(EnElfgrp* this, PlayState* play);
+void EnElfgrp_DoNothing(EnElfgrp* this, PlayState* play);
void func_80A3A7FC(EnElfgrp* this, PlayState* play);
void func_80A3A8F8(EnElfgrp* this, PlayState* play);
+// State flags
+#define ELFGRP_STATE_0 (1 << 0)
+#define ELFGRP_STATE_1 (1 << 1)
+#define ELFGRP_STATE_2 (1 << 2)
+#define ELFGRP_STATE_3 (1 << 3)
+#define ELFGRP_STATE_4 (1 << 4)
+
+// Used for the type in EnElfgrp_SpawnStrayFairies
+typedef enum ElfgrpSpawnedFairyTypes {
+ /* 0 */ SPAWNED_STRAY_FAIRY_TYPE_PRESENT, // STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN
+ /* 1 */ SPAWNED_STRAY_FAIRY_TYPE_RETURNING // STRAY_FAIRY_TYPE_RETURNING_TO_FOUNTAIN
+} ElfgrpSpawnedFairyTypes;
+
ActorInit En_Elfgrp_InitVars = {
ACTOR_EN_ELFGRP,
ACTORCAT_PROP,
@@ -47,7 +78,15 @@ ActorInit En_Elfgrp_InitVars = {
(ActorFunc)NULL,
};
-void func_80A396B0(EnElfgrp* this, s32 numCutscenes) {
+/**
+ * Set the actor's cutscene id to a later one, or -1 if run out.
+ *
+ * @note This is only expected to be called in Init when this actor has the first cutscene set, but can also work for
+ * later cutscenes if \p numCutscenes is set correcly.
+ *
+ * @param numCutscenes Number of cutscenes in the list to skip forward to set this one.
+ */
+void EnElfgrp_SetCutscene(EnElfgrp* this, s32 numCutscenes) {
while (numCutscenes > 0) {
if (this->actor.csId == CS_ID_NONE) {
break;
@@ -61,113 +100,118 @@ void func_80A396B0(EnElfgrp* this, s32 numCutscenes) {
void EnElfgrp_Init(Actor* thisx, PlayState* play) {
s32 pad;
EnElfgrp* this = THIS;
- s32 sp24;
+ s32 numberInFountain;
- this->unk_147 = ENELFGRP_GET(&this->actor);
+ this->type = ENELFGRP_GET_TYPE(&this->actor);
this->unk_148 = 0;
- this->unk_14A = 0;
+ this->stateFlags = 0;
this->actor.focus.pos.y += 40.0f;
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
- switch (this->unk_147) {
- case ENELFGRP_1:
- case ENELFGRP_2:
- case ENELFGRP_3:
- case ENELFGRP_4:
- this->unk_148 = this->unk_147 - 1;
- sp24 = func_80A39C1C(play, this->unk_147);
- this->unk_146 = 1 << this->unk_147;
+ switch (this->type) {
+ case ENELFGRP_TYPE_POWER:
+ case ENELFGRP_TYPE_WISDOM:
+ case ENELFGRP_TYPE_COURAGE:
+ case ENELFGRP_TYPE_KINDNESS:
+ this->unk_148 = this->type - 1;
+ numberInFountain = EnElfgrp_GetFountainFairiesCount(play, this->type);
+ this->talkedOnceFlag = 1 << this->type;
- if (sp24 < 25) {
- func_80A39DC8(this, play, sp24, 0);
+ if (numberInFountain < STRAY_FAIRY_TOTAL) {
+ EnElfgrp_SpawnStrayFairies(this, play, numberInFountain, SPAWNED_STRAY_FAIRY_TYPE_PRESENT);
}
- if (sp24 >= 25) {
+ if (numberInFountain >= STRAY_FAIRY_TOTAL) {
this->actionFunc = func_80A3A520;
- func_80A396B0(this, 2);
- return;
+ EnElfgrp_SetCutscene(this, 2);
+ break;
}
- if ((func_80A39BD0(play, this->unk_147) + sp24) >= 25) {
+ if ((EnElfgrp_GetHeldFairiesCount(play, this->type) + numberInFountain) >= STRAY_FAIRY_TOTAL) {
this->actionFunc = func_80A3A398;
- switch (this->unk_147) {
- case ENELFGRP_1:
- if (CHECK_WEEKEVENTREG(WEEKEVENTREG_23_02)) {
- func_80A396B0(this, 1);
+ switch (this->type) {
+ case ENELFGRP_TYPE_POWER:
+ if (CHECK_WEEKEVENTREG(WEEKEVENTREG_OBTAINED_GREAT_SPIN_ATTACK)) {
+ EnElfgrp_SetCutscene(this, 1);
} else {
- this->unk_14A |= 4;
+ this->stateFlags |= ELFGRP_STATE_2;
}
break;
- case ENELFGRP_2:
+ case ENELFGRP_TYPE_WISDOM:
if (gSaveContext.save.saveInfo.playerData.isDoubleMagicAcquired == true) {
- func_80A396B0(this, 1);
+ EnElfgrp_SetCutscene(this, 1);
}
break;
- case ENELFGRP_3:
+ case ENELFGRP_TYPE_COURAGE:
if (gSaveContext.save.saveInfo.playerData.doubleDefense) {
- func_80A396B0(this, 1);
+ EnElfgrp_SetCutscene(this, 1);
}
break;
- case ENELFGRP_4:
+ case ENELFGRP_TYPE_KINDNESS:
if (INV_CONTENT(ITEM_SWORD_GREAT_FAIRY) == ITEM_SWORD_GREAT_FAIRY) {
- func_80A396B0(this, 1);
+ EnElfgrp_SetCutscene(this, 1);
} else {
- this->unk_14A |= 0x10;
+ this->stateFlags |= ELFGRP_STATE_4;
}
break;
default:
break;
}
- } else if (func_80A39BD0(play, this->unk_147)) {
+ } else if (EnElfgrp_GetHeldFairiesCount(play, this->type)) {
this->actionFunc = func_80A3A7FC;
- this->actor.textId = (this->unk_147 * 3) + 0x581;
+ this->actor.textId = (this->type * 3) + 0x581;
} else {
this->actionFunc = func_80A3A8F8;
- if ((gSaveContext.save.saveInfo.weekEventReg[9] & this->unk_146)) {
- this->actor.textId = (this->unk_147 * 3) + 0x580;
+
+ if ((gSaveContext.save.saveInfo.weekEventReg[9] & this->talkedOnceFlag)) { // talked for first time
+ this->actor.textId = (this->type * 3) + 0x580;
} else {
- this->actor.textId = (this->unk_147 * 3) + 0x57F;
+ this->actor.textId = (this->type * 3) + 0x57F;
}
}
break;
- default:
- sp24 = func_80A39C1C(play, 0);
- this->unk_146 = ENELFGRP_1;
- if (sp24 >= 25) {
+ default: // ENELFGRP_TYPE_MAGIC
+ numberInFountain = EnElfgrp_GetFountainFairiesCount(play, ENELFGRP_TYPE_MAGIC);
+ this->talkedOnceFlag = 1 << ENELFGRP_TYPE_MAGIC;
+
+ if (numberInFountain >= STRAY_FAIRY_TOTAL) {
this->actionFunc = func_80A3A520;
- if ((this->actor.home.rot.z != 0) && Flags_GetSwitch(play, this->actor.home.rot.z)) {
- this->actionFunc = func_80A3A600;
+
+ if ((ENELFGRP_GET_SWITCHFLAG_ROT(&this->actor) != 0) &&
+ Flags_GetSwitch(play, ENELFGRP_GET_SWITCHFLAG_ROT(&this->actor))) {
+ this->actionFunc = EnElfgrp_DoNothing;
} else if (INV_CONTENT(ITEM_MASK_GREAT_FAIRY) == ITEM_MASK_GREAT_FAIRY) {
- func_80A396B0(this, 4);
+ EnElfgrp_SetCutscene(this, 4);
} else if (INV_CONTENT(ITEM_MASK_DEKU) != ITEM_MASK_DEKU) {
- func_80A396B0(this, 5);
+ EnElfgrp_SetCutscene(this, 5);
} else {
- this->unk_14A |= 2;
- func_80A396B0(this, 6);
+ this->stateFlags |= ELFGRP_STATE_1;
+ EnElfgrp_SetCutscene(this, 6);
}
} else if (CHECK_WEEKEVENTREG(WEEKEVENTREG_08_80)) {
- func_80A39DC8(this, play, 24, 0);
+ EnElfgrp_SpawnStrayFairies(this, play, STRAY_FAIRY_TOTAL - 1, SPAWNED_STRAY_FAIRY_TYPE_PRESENT);
this->actionFunc = func_80A3A398;
+
if (INV_CONTENT(ITEM_MASK_DEKU) == ITEM_MASK_DEKU) {
if (INV_CONTENT(ITEM_MASK_GREAT_FAIRY) == ITEM_MASK_GREAT_FAIRY) {
- func_80A396B0(this, 2);
+ EnElfgrp_SetCutscene(this, 2);
} else {
- func_80A396B0(this, 3);
- this->unk_14A |= 2;
+ EnElfgrp_SetCutscene(this, 3);
+ this->stateFlags |= ELFGRP_STATE_1;
}
} else if (gSaveContext.save.saveInfo.playerData.isMagicAcquired == true) {
- func_80A396B0(this, 1);
+ EnElfgrp_SetCutscene(this, 1);
}
} else {
- func_80A39DC8(this, play, 24, 0);
+ EnElfgrp_SpawnStrayFairies(this, play, STRAY_FAIRY_TOTAL - 1, SPAWNED_STRAY_FAIRY_TYPE_PRESENT);
this->actionFunc = func_80A3A8F8;
- if ((gSaveContext.save.saveInfo.weekEventReg[9] & this->unk_146)) {
+ if ((gSaveContext.save.saveInfo.weekEventReg[9] & this->talkedOnceFlag)) {
this->actor.textId = 0x580;
} else {
this->actor.textId = 0x578;
@@ -181,116 +225,119 @@ void EnElfgrp_Init(Actor* thisx, PlayState* play) {
void EnElfgrp_Destroy(Actor* thisx, PlayState* play) {
}
-s32 func_80A39BD0(PlayState* play, s32 arg2) {
- if ((arg2 < 1) || (arg2 >= 5)) {
+// Number of Stray Fairies currently held by Player
+s32 EnElfgrp_GetHeldFairiesCount(PlayState* play, s32 type) {
+ if ((type <= ENELFGRP_TYPE_MAGIC) || (type > ENELFGRP_TYPE_KINDNESS)) {
return 0;
}
- return (((void)0, gSaveContext.save.saveInfo.inventory.strayFairies[arg2 - 1]) - func_80A39C1C(play, arg2)) + 10;
+ // Number in fountain originally + total number collected - number currently in fountain
+ return (STRAY_FAIRY_TOTAL - STRAY_FAIRY_SCATTERED_TOTAL) +
+ ((void)0, gSaveContext.save.saveInfo.inventory.strayFairies[type - 1]) -
+ EnElfgrp_GetFountainFairiesCount(play, type);
}
-s32 func_80A39C1C(PlayState* play, s32 arg1) {
- // the permanentSceneFlags access here is in the form
- // struct {
- // u32 clockTown : 1;
- // u32 fountains[4] : 5;
- // } FairyFountains;
- // where arg1 is:
- // 0: clocktown
- // 1: woodfall,
- // 2: snowhead,
- // 3: great bay,
- // 4: stone tower
- // clocktown is handled separately, and then the fountains are looked up as array indexing
+// Number of Stray Fairies in currently in Fountain
+s32 EnElfgrp_GetFountainFairiesCount(PlayState* play, s32 type) {
+ s32 numberInFountain;
- s32 temp_v1;
-
- if ((arg1 < 0) || (arg1 >= 5)) {
+ if ((type < ENELFGRP_TYPE_MAGIC) || (type > ENELFGRP_TYPE_KINDNESS)) {
return 0;
}
- if (arg1 == 0) {
+ if (type == ENELFGRP_TYPE_MAGIC) {
if (gSaveContext.save.saveInfo.permanentSceneFlags[play->sceneId].unk_14 & 1) {
- return 25;
+ return STRAY_FAIRY_TOTAL;
+ } else {
+ return STRAY_FAIRY_TOTAL - 1;
}
- return 24;
}
- temp_v1 = (gSaveContext.save.saveInfo.permanentSceneFlags[play->sceneId].unk_14 >> (((arg1 - 1) * 5) + 1)) & 0x1F;
- if (temp_v1 < 10) {
- temp_v1 = 10;
- } else if (temp_v1 > 25) {
- temp_v1 = 25;
+ numberInFountain =
+ (gSaveContext.save.saveInfo.permanentSceneFlags[play->sceneId].unk_14 >> (((type - 1) * 5) + 1)) & 0x1F;
+ if (numberInFountain < STRAY_FAIRY_TOTAL - STRAY_FAIRY_SCATTERED_TOTAL) {
+ numberInFountain = STRAY_FAIRY_TOTAL - STRAY_FAIRY_SCATTERED_TOTAL;
+ } else if (numberInFountain > STRAY_FAIRY_TOTAL) {
+ numberInFountain = STRAY_FAIRY_TOTAL;
}
- return temp_v1;
+ return numberInFountain;
}
-void func_80A39CD4(PlayState* play, s32 arg1, s32 arg2) {
- if ((arg1 < 0) || (arg1 > 4) || (arg2 < 10) || (arg2 > 25)) {
+// Update number of Stray Fairies in Fountain
+void EnElfgrp_SetFountainFairiesCount(PlayState* play, s32 type, s32 newCount) {
+ if ((type < ENELFGRP_TYPE_MAGIC) || (type > ENELFGRP_TYPE_KINDNESS) ||
+ (newCount < (STRAY_FAIRY_TOTAL - STRAY_FAIRY_SCATTERED_TOTAL)) || (newCount > STRAY_FAIRY_TOTAL)) {
return;
}
- if (arg1 == 0) {
- if (arg2 == 25) {
+ if (type == ENELFGRP_TYPE_MAGIC) {
+ if (newCount == STRAY_FAIRY_TOTAL) {
gSaveContext.save.saveInfo.permanentSceneFlags[play->sceneId].unk_14 |= 1;
} else {
gSaveContext.save.saveInfo.permanentSceneFlags[play->sceneId].unk_14 &= ~1;
}
} else {
- gSaveContext.save.saveInfo.permanentSceneFlags[play->sceneId].unk_14 &= ~(0x1F << ((arg1 * 5) - 4));
- gSaveContext.save.saveInfo.permanentSceneFlags[play->sceneId].unk_14 |= arg2 << ((arg1 * 5) - 4);
+ gSaveContext.save.saveInfo.permanentSceneFlags[play->sceneId].unk_14 &= ~(0x1F << ((type * 5) - 4));
+ gSaveContext.save.saveInfo.permanentSceneFlags[play->sceneId].unk_14 |= newCount << ((type * 5) - 4);
}
}
-void func_80A39DC8(EnElfgrp* this, PlayState* play, s32 arg2, s32 arg3) {
+void EnElfgrp_SpawnStrayFairies(EnElfgrp* this, PlayState* play, s32 count, s32 fairyType) {
s32 pad;
s32 i;
- Actor* elforg;
- s32 params;
- Vec3f sp6C;
+ Actor* strayFairy;
+ s32 strayFairyParams;
+ Vec3f spawnCenterPos;
Player* player = GET_PLAYER(play);
- if (arg3 == 0) {
- this->unk_14A |= 8;
+ if (fairyType == 0) {
+ this->stateFlags |= ELFGRP_STATE_3;
}
- if (arg3 == 0) {
- sp6C = this->actor.world.pos;
- sp6C.y += 20.0f;
- params = STRAY_FAIRY_PARAMS(0, this->unk_147, STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN);
+ if (fairyType == 0) {
+ spawnCenterPos = this->actor.world.pos;
+ spawnCenterPos.y += 20.0f;
+ strayFairyParams = STRAY_FAIRY_PARAMS(0, this->type, STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN);
} else {
- sp6C = player->actor.world.pos;
- sp6C.y += 20.0f;
- params = STRAY_FAIRY_PARAMS(0, this->unk_147, STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN);
+ spawnCenterPos = player->actor.world.pos;
+ spawnCenterPos.y += 20.0f;
+ strayFairyParams = STRAY_FAIRY_PARAMS(0, this->type, STRAY_FAIRY_TYPE_RETURNING_TO_FOUNTAIN);
}
- for (i = 0; i < arg2; i++) {
- elforg = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELFORG, Rand_CenteredFloat(20.0f) + sp6C.x, sp6C.y,
- Rand_CenteredFloat(20.0f) + sp6C.z, 0, 0, 0, params);
- if (elforg == NULL) {
+ for (i = 0; i < count; i++) {
+ strayFairy =
+ Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELFORG, Rand_CenteredFloat(20.0f) + spawnCenterPos.x,
+ spawnCenterPos.y, Rand_CenteredFloat(20.0f) + spawnCenterPos.z, 0, 0, 0, strayFairyParams);
+
+ if (strayFairy == NULL) {
continue;
}
- elforg->home.pos.x = this->actor.home.pos.x;
- elforg->home.pos.y = this->actor.home.pos.y + 20.0f;
- elforg->home.pos.z = this->actor.home.pos.z;
+ strayFairy->home.pos.x = this->actor.home.pos.x;
+ strayFairy->home.pos.y = this->actor.home.pos.y + 20.0f;
+ strayFairy->home.pos.z = this->actor.home.pos.z;
}
}
-s32 func_80A39F50(PlayState* play) {
+/**
+ * Tell any spawned Stray Fairies to come to the Fountain center.
+ *
+ * @return s32 always 0
+ */
+s32 EnElfgrp_SummonStrayFairies(PlayState* play) {
Actor* itemAction = play->actorCtx.actorLists[ACTORCAT_ITEMACTION].first;
- EnElforg* elfOrg;
+ EnElforg* strayFairy;
while (itemAction != NULL) {
if ((itemAction->id != ACTOR_EN_ELFORG) ||
((STRAY_FAIRY_TYPE(itemAction) != STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN) &&
- (STRAY_FAIRY_TYPE(itemAction) != STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN))) {
+ (STRAY_FAIRY_TYPE(itemAction) != STRAY_FAIRY_TYPE_RETURNING_TO_FOUNTAIN))) {
itemAction = itemAction->next;
continue;
}
- elfOrg = (EnElforg*)itemAction;
- if (!(elfOrg->strayFairyFlags & STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME)) {
- elfOrg->strayFairyFlags |= STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME;
+ strayFairy = (EnElforg*)itemAction;
+ if (!(strayFairy->strayFairyFlags & STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME)) {
+ strayFairy->strayFairyFlags |= STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME;
}
itemAction = itemAction->next;
}
@@ -298,50 +345,58 @@ s32 func_80A39F50(PlayState* play) {
return 0;
}
-s32 func_80A39FBC(PlayState* play) {
+/**
+ * Make the Stray Fairies in the fountain spin quickly when healing Player.
+ *
+ * @return s32 time to spend in healing action.
+ */
+s32 EnElfgrp_SpinStrayFairies(PlayState* play) {
Actor* itemAction = play->actorCtx.actorLists[ACTORCAT_ITEMACTION].first;
- EnElforg* elfOrg;
- s32 phi_v1 = 30;
+ EnElforg* strayFairy;
+ s32 timer = 30;
while (itemAction != NULL) {
if ((itemAction->id != ACTOR_EN_ELFORG) ||
((STRAY_FAIRY_TYPE(itemAction) != STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN) &&
- (STRAY_FAIRY_TYPE(itemAction) != STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN))) {
+ (STRAY_FAIRY_TYPE(itemAction) != STRAY_FAIRY_TYPE_RETURNING_TO_FOUNTAIN))) {
itemAction = itemAction->next;
continue;
}
- elfOrg = (EnElforg*)itemAction;
- if (!(elfOrg->strayFairyFlags & STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN)) {
- elfOrg->strayFairyFlags |= STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN;
- if (phi_v1 >= 100) {
- return phi_v1;
+ strayFairy = (EnElforg*)itemAction;
+ if (!(strayFairy->strayFairyFlags & STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN)) {
+ strayFairy->strayFairyFlags |= STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN;
+ if (timer >= 100) {
+ return timer;
}
- elfOrg->secondaryTimer = phi_v1;
- phi_v1 += 5;
+ strayFairy->secondaryTimer = timer;
+ timer += 5;
}
itemAction = itemAction->next;
}
- return phi_v1;
+ return timer;
}
-void func_80A3A044(PlayState* play) {
+/**
+ * Tell the Stray Fairies to disappear, before reviving the Great Fairy
+ */
+void EnElfgrp_VanishStrayFairies(PlayState* play) {
Actor* itemAction = play->actorCtx.actorLists[ACTORCAT_ITEMACTION].first;
- EnElforg* elfOrg;
+ EnElforg* strayFairy;
while (itemAction != NULL) {
if ((itemAction->id != ACTOR_EN_ELFORG) ||
((STRAY_FAIRY_TYPE(itemAction) != STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN) &&
- (STRAY_FAIRY_TYPE(itemAction) != STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN))) {
+ (STRAY_FAIRY_TYPE(itemAction) != STRAY_FAIRY_TYPE_RETURNING_TO_FOUNTAIN))) {
itemAction = itemAction->next;
continue;
}
- elfOrg = (EnElforg*)itemAction;
- elfOrg->actor.home.rot.x = 0x14;
- elfOrg->strayFairyFlags |= STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS;
+ strayFairy = (EnElforg*)itemAction;
+ STRAY_FAIRY_SPARKLE_COUNT(&strayFairy->actor) = 20;
+ strayFairy->strayFairyFlags |= STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS;
itemAction = itemAction->next;
}
@@ -349,68 +404,70 @@ void func_80A3A044(PlayState* play) {
void func_80A3A0AC(EnElfgrp* this, PlayState* play) {
if (!Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_100)) {
- this->actionFunc = func_80A3A600;
+ this->actionFunc = EnElfgrp_DoNothing;
CutsceneManager_Stop(this->actor.csId);
}
}
void func_80A3A0F4(EnElfgrp* this, PlayState* play) {
- if (this->unk_144 == 10) {
+ if (this->timer == 10) {
Audio_PlaySfx(NA_SE_SY_WHITE_OUT_T);
- if (ENELFGRP_GET(&this->actor) < ENELFGRP_4) {
+ if (ENELFGRP_GET_TYPE(&this->actor) < ENELFGRP_TYPE_KINDNESS) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x,
this->actor.world.pos.y + 30.0f, this->actor.world.pos.z, 0, 0, 0,
- ENELFGRP_GET(&this->actor) + ENELFGRP_4);
- } else {
+ ENELFGRP_GET_TYPE(&this->actor) + DEMO_EFFECT_TYPE_LIGHT_BASE);
+ } else { // ENELFGRP_TYPE_KINDNESS
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->actor.world.pos.x,
- this->actor.world.pos.y + 30.0f, this->actor.world.pos.z, 0, 0, 0, 4);
+ this->actor.world.pos.y + 30.0f, this->actor.world.pos.z, 0, 0, 0,
+ DEMO_EFFECT_TYPE_LIGHT_DARK_YELLOW);
}
}
- if ((this->unk_144 > 10) && (this->unk_14A & 1)) {
+ if ((this->timer > 10) && (this->stateFlags & ELFGRP_STATE_0)) {
Actor_PlaySfx_Flagged(&this->actor, NA_SE_EV_FAIRY_GROUP_FRY - SFX_FLAG);
}
- if (this->unk_144 == 0) {
+ if (this->timer == 0) {
this->actionFunc = func_80A3A0AC;
}
}
void func_80A3A210(EnElfgrp* this, PlayState* play) {
- if (this->unk_144 == 0) {
+ if (this->timer == 0) {
this->actionFunc = func_80A3A0F4;
- func_80A3A044(play);
- this->unk_144 = 30;
+ EnElfgrp_VanishStrayFairies(play);
+ this->timer = 30;
}
- if (this->unk_14A & 1) {
+ if (this->stateFlags & ELFGRP_STATE_0) {
Actor_PlaySfx_Flagged(&this->actor, NA_SE_EV_FAIRY_GROUP_FRY - SFX_FLAG);
}
}
void func_80A3A274(EnElfgrp* this, PlayState* play) {
if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_100)) {
- if (this->unk_14A & 1) {
+ if (this->stateFlags & ELFGRP_STATE_0) {
Actor_PlaySfx_Flagged(&this->actor, NA_SE_PL_CHIBI_FAIRY_HEAL - SFX_FLAG);
}
switch (play->csCtx.actorCues[Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_100)]->id) {
case 2:
- if (!(this->unk_14A & 1)) {
- if (this->unk_147 == ENELFGRP_0) {
- func_80A39DC8(this, play, 1, 1);
+ if (!(this->stateFlags & ELFGRP_STATE_0)) {
+ if (this->type == ENELFGRP_TYPE_MAGIC) { // Clock Town
+ EnElfgrp_SpawnStrayFairies(this, play, 1, SPAWNED_STRAY_FAIRY_TYPE_RETURNING);
} else {
- func_80A39DC8(this, play, func_80A39BD0(play, this->unk_147), 1);
+ EnElfgrp_SpawnStrayFairies(this, play, EnElfgrp_GetHeldFairiesCount(play, this->type),
+ SPAWNED_STRAY_FAIRY_TYPE_RETURNING);
}
- this->unk_14A |= 1;
- func_80A39CD4(play, this->unk_147, 25);
+ this->stateFlags |= ELFGRP_STATE_0;
+ EnElfgrp_SetFountainFairiesCount(play, this->type, STRAY_FAIRY_TOTAL);
}
break;
case 3:
- func_80A39F50(play);
+ EnElfgrp_SummonStrayFairies(play);
this->actionFunc = func_80A3A210;
- this->unk_144 = 90;
+ this->timer = 90;
break;
default:
@@ -423,28 +480,30 @@ void func_80A3A398(EnElfgrp* this, PlayState* play) {
if (CutsceneManager_IsNext(this->actor.csId)) {
CutsceneManager_StartWithPlayerCs(this->actor.csId, &this->actor);
this->actionFunc = func_80A3A274;
- Flags_UnsetSwitch(play, ENELFGRP_GET_FE00(&this->actor));
- if (this->unk_14A & 2) {
+ Flags_UnsetSwitch(play, ENELFGRP_GET_SWITCHFLAG_PARAMS(&this->actor));
+
+ if (this->stateFlags & ELFGRP_STATE_1) {
Item_Give(play, ITEM_MASK_GREAT_FAIRY);
}
- if ((this->unk_14A & 4) != 0) {
- SET_WEEKEVENTREG(WEEKEVENTREG_23_02);
+ if (this->stateFlags & ELFGRP_STATE_2) {
+ SET_WEEKEVENTREG(WEEKEVENTREG_OBTAINED_GREAT_SPIN_ATTACK);
}
- if (this->unk_14A & 0x10) {
+ if (this->stateFlags & ELFGRP_STATE_4) {
Item_Give(play, ITEM_SWORD_GREAT_FAIRY);
}
- this->unk_14A &= ~8;
+
+ this->stateFlags &= ~ELFGRP_STATE_3;
} else if (this->actor.xzDistToPlayer < 350.0f) {
CutsceneManager_Queue(this->actor.csId);
}
}
void func_80A3A484(EnElfgrp* this, PlayState* play) {
- if (this->unk_144 == 0) {
+ if (this->timer == 0) {
this->actionFunc = func_80A3A0F4;
- this->unk_144 = 30;
+ this->timer = 30;
}
}
@@ -454,51 +513,51 @@ void func_80A3A4AC(EnElfgrp* this, PlayState* play) {
if (cueId == 3) {
this->actionFunc = func_80A3A484;
- this->unk_144 = 90;
+ this->timer = 90;
}
}
}
void func_80A3A520(EnElfgrp* this, PlayState* play) {
if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_103)) {
- this->actionFunc = func_80A3A600;
+ this->actionFunc = EnElfgrp_DoNothing;
} else if (CutsceneManager_IsNext(this->actor.csId)) {
CutsceneManager_StartWithPlayerCs(this->actor.csId, &this->actor);
this->actionFunc = func_80A3A4AC;
- Flags_SetSwitch(play, ENELFGRP_GET_FE00(&this->actor));
+ Flags_SetSwitch(play, ENELFGRP_GET_SWITCHFLAG_PARAMS(&this->actor));
- if (this->unk_14A & 2) {
+ if (this->stateFlags & ELFGRP_STATE_1) {
Item_Give(play, ITEM_MASK_GREAT_FAIRY);
}
- if (this->actor.home.rot.z != 0) {
- Flags_SetSwitch(play, this->actor.home.rot.z);
+ if (ENELFGRP_GET_SWITCHFLAG_ROT(&this->actor) != 0) {
+ Flags_SetSwitch(play, ENELFGRP_GET_SWITCHFLAG_ROT(&this->actor));
}
} else if (this->actor.xzDistToPlayer < 350.0f) {
CutsceneManager_Queue(this->actor.csId);
}
}
-void func_80A3A600(EnElfgrp* this, PlayState* play) {
+void EnElfgrp_DoNothing(EnElfgrp* this, PlayState* play) {
}
-void func_80A3A610(EnElfgrp* this, PlayState* play) {
+void EnElfgrp_HealPlayer(EnElfgrp* this, PlayState* play) {
Player* player = GET_PLAYER(play);
- if (this->unk_144 == 60) {
+ if (this->timer == 60) {
Magic_Add(play, MAGIC_FILL_TO_CAPACITY);
- gSaveContext.healthAccumulator = 320;
+ gSaveContext.healthAccumulator = 0x140;
}
- if (this->unk_144 > 0) {
+ if (this->timer > 0) {
player->actor.freezeTimer = 100;
player->stateFlags1 |= PLAYER_STATE1_20000000;
Actor_PlaySfx(&this->actor, NA_SE_EV_FAIRY_GROUP_HEAL - SFX_FLAG);
} else {
player->actor.freezeTimer = 0;
player->stateFlags1 &= ~PLAYER_STATE1_20000000;
- this->actionFunc = func_80A3A600;
- this->unk_14A |= 8;
+ this->actionFunc = EnElfgrp_DoNothing;
+ this->stateFlags |= ELFGRP_STATE_3;
}
}
@@ -509,9 +568,9 @@ void func_80A3A6F4(EnElfgrp* this, PlayState* play) {
if (Actor_TextboxIsClosing(&this->actor, play)) {
player->actor.freezeTimer = 100;
player->stateFlags1 |= PLAYER_STATE1_20000000;
- this->unk_144 = func_80A39FBC(play);
- this->actionFunc = func_80A3A610;
- this->unk_14A &= ~8;
+ this->timer = EnElfgrp_SpinStrayFairies(play);
+ this->actionFunc = EnElfgrp_HealPlayer;
+ this->stateFlags &= ~ELFGRP_STATE_3;
}
}
@@ -521,25 +580,27 @@ void func_80A3A77C(EnElfgrp* this, PlayState* play) {
player->actor.freezeTimer = 100;
player->stateFlags1 |= PLAYER_STATE1_20000000;
if (Actor_TextboxIsClosing(&this->actor, play)) {
- this->unk_144 = func_80A39FBC(play);
- this->actionFunc = func_80A3A610;
- this->unk_14A &= ~8;
+ this->timer = EnElfgrp_SpinStrayFairies(play);
+ this->actionFunc = EnElfgrp_HealPlayer;
+ this->stateFlags &= ~ELFGRP_STATE_3;
}
}
void func_80A3A7FC(EnElfgrp* this, PlayState* play) {
- s32 temp_s0;
+ s32 curTotalFairies;
if (Actor_ProcessTalkRequest(&this->actor, &play->state)) {
- gSaveContext.save.saveInfo.weekEventReg[9] |= this->unk_146;
+ gSaveContext.save.saveInfo.weekEventReg[9] |= this->talkedOnceFlag;
this->actionFunc = func_80A3A6F4;
- temp_s0 = func_80A39BD0(play, this->unk_147);
- func_80A39DC8(this, play, temp_s0, 1);
- temp_s0 += func_80A39C1C(play, this->unk_147);
- if (temp_s0 > 25) {
- temp_s0 = 25;
+
+ curTotalFairies = EnElfgrp_GetHeldFairiesCount(play, this->type);
+ EnElfgrp_SpawnStrayFairies(this, play, curTotalFairies, SPAWNED_STRAY_FAIRY_TYPE_RETURNING);
+ curTotalFairies += EnElfgrp_GetFountainFairiesCount(play, this->type);
+ if (curTotalFairies > STRAY_FAIRY_TOTAL) {
+ curTotalFairies = STRAY_FAIRY_TOTAL;
}
- func_80A39CD4(play, this->unk_147, temp_s0);
+
+ EnElfgrp_SetFountainFairiesCount(play, this->type, curTotalFairies);
} else if (this->actor.xzDistToPlayer < 280.0f) {
this->actor.flags |= ACTOR_FLAG_10000;
Actor_OfferTalk(&this->actor, play, 300.0f);
@@ -551,13 +612,13 @@ void func_80A3A8F8(EnElfgrp* this, PlayState* play) {
Player* player = GET_PLAYER(play);
if (Actor_ProcessTalkRequest(&this->actor, &play->state)) {
- gSaveContext.save.saveInfo.weekEventReg[9] |= this->unk_146;
+ gSaveContext.save.saveInfo.weekEventReg[9] |= this->talkedOnceFlag;
this->actionFunc = func_80A3A6F4;
return;
}
- if (this->unk_147 != ENELFGRP_0) {
- if (func_80A39BD0(play, this->unk_147) > 0) {
+ if (this->type != ENELFGRP_TYPE_MAGIC) {
+ if (EnElfgrp_GetHeldFairiesCount(play, this->type) > 0) {
this->actionFunc = func_80A3A7FC;
return;
}
@@ -570,7 +631,7 @@ void func_80A3A8F8(EnElfgrp* this, PlayState* play) {
player->stateFlags1 |= PLAYER_STATE1_20000000;
Message_StartTextbox(play, this->actor.textId, &this->actor);
this->actionFunc = func_80A3A77C;
- gSaveContext.save.saveInfo.weekEventReg[9] |= this->unk_146;
+ gSaveContext.save.saveInfo.weekEventReg[9] |= this->talkedOnceFlag;
} else {
this->actor.flags |= ACTOR_FLAG_10000;
Actor_OfferTalk(&this->actor, play, 100.0f);
@@ -585,11 +646,11 @@ void EnElfgrp_Update(Actor* thisx, PlayState* play) {
this->actionFunc(this, play);
- if (this->unk_14A & 8) {
+ if (this->stateFlags & ELFGRP_STATE_3) {
Actor_PlaySfx(&this->actor, NA_SE_EV_FAIRY_GROUP_FRY - SFX_FLAG);
}
- if (this->unk_144 != 0) {
- this->unk_144--;
+ if (this->timer != 0) {
+ this->timer--;
}
}
diff --git a/src/overlays/actors/ovl_En_Elfgrp/z_en_elfgrp.h b/src/overlays/actors/ovl_En_Elfgrp/z_en_elfgrp.h
index 692a76d826..d9767fb2fa 100644
--- a/src/overlays/actors/ovl_En_Elfgrp/z_en_elfgrp.h
+++ b/src/overlays/actors/ovl_En_Elfgrp/z_en_elfgrp.h
@@ -2,29 +2,32 @@
#define Z_EN_ELFGRP_H
#include "global.h"
+#include "overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h"
struct EnElfgrp;
typedef void (*EnElfgrpActionFunc)(struct EnElfgrp*, PlayState*);
-#define ENELFGRP_GET(thisx) ((thisx)->params & 0xF)
-#define ENELFGRP_GET_FE00(thisx) (((thisx)->params & 0xFE00) >> 9)
+#define ENELFGRP_GET_TYPE(thisx) ((thisx)->params & 0xF) //!< Same type as Great Fairies
+#define ENELFGRP_GET_SWITCHFLAG_PARAMS(thisx) (((thisx)->params & 0xFE00) >> 9)
+#define ENELFGRP_GET_SWITCHFLAG_ROT(thisx) ((thisx)->home.rot.z)
-typedef enum {
- /* 0 */ ENELFGRP_0,
- /* 2 */ ENELFGRP_1,
- /* 2 */ ENELFGRP_2,
- /* 3 */ ENELFGRP_3,
- /* 4 */ ENELFGRP_4
-} EnElfgrpParam;
+typedef enum ElfgrpType {
+ /* 0 */ ENELFGRP_TYPE_MAGIC = GREAT_FAIRY_TYPE_MAGIC,
+ /* 1 */ ENELFGRP_TYPE_POWER = GREAT_FAIRY_TYPE_POWER,
+ /* 2 */ ENELFGRP_TYPE_WISDOM = GREAT_FAIRY_TYPE_WISDOM,
+ /* 3 */ ENELFGRP_TYPE_COURAGE = GREAT_FAIRY_TYPE_COURAGE,
+ /* 4 */ ENELFGRP_TYPE_KINDNESS = GREAT_FAIRY_TYPE_KINDNESS,
+ /* 5 */ ENELFGRP_TYPE_MAX
+} ElfgrpType;
typedef struct EnElfgrp {
/* 0x000 */ Actor actor;
- /* 0x144 */ s16 unk_144;
- /* 0x146 */ u8 unk_146;
- /* 0x147 */ u8 unk_147;
- /* 0x148 */ s8 unk_148;
- /* 0x14A */ u16 unk_14A;
+ /* 0x144 */ s16 timer;
+ /* 0x146 */ u8 talkedOnceFlag;
+ /* 0x147 */ u8 type;
+ /* 0x148 */ s8 unk_148; // set and not used
+ /* 0x14A */ u16 stateFlags;
/* 0x14C */ EnElfgrpActionFunc actionFunc;
} EnElfgrp; // size = 0x150
diff --git a/src/overlays/actors/ovl_En_Elforg/z_en_elforg.c b/src/overlays/actors/ovl_En_Elforg/z_en_elforg.c
index f57f8e0662..27dc844e77 100644
--- a/src/overlays/actors/ovl_En_Elforg/z_en_elforg.c
+++ b/src/overlays/actors/ovl_En_Elforg/z_en_elforg.c
@@ -96,7 +96,7 @@ void EnElforg_Init(Actor* thisx, PlayState* play) {
case STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN:
case STRAY_FAIRY_TYPE_BUBBLE:
case STRAY_FAIRY_TYPE_CHEST:
- case STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN:
+ case STRAY_FAIRY_TYPE_RETURNING_TO_FOUNTAIN:
break;
default:
@@ -121,7 +121,7 @@ void EnElforg_Init(Actor* thisx, PlayState* play) {
this->targetDistanceFromHome = Rand_ZeroFloat(100.0f) + 50.0f;
break;
- case STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN:
+ case STRAY_FAIRY_TYPE_RETURNING_TO_FOUNTAIN:
EnElforg_InitializeParams(this);
this->actionFunc = EnElforg_TurnInFairy;
this->secondaryTimer = 60;
@@ -324,6 +324,7 @@ void EnElforg_TurnInFairy(EnElforg* this, PlayState* play) {
void EnElforg_QuicklyCircleFairyFountain(EnElforg* this, PlayState* play) {
SkelAnime_Update(&this->skelAnime);
EnElforg_MoveToTargetFairyFountain(this, &this->actor.home.pos);
+
if (this->secondaryTimer <= 30) {
this->actionFunc = EnElforg_TurnInFairy;
}
@@ -367,9 +368,9 @@ void EnElforg_FreeFloatingFairyFountain(EnElforg* this, PlayState* play) {
if (this->strayFairyFlags & STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS) {
// This happens right before the Great Fairy appears once all
// Stray Fairies are saved.
- if (this->actor.home.rot.x > 0) {
+ if (STRAY_FAIRY_SPARKLE_COUNT(&this->actor) > 0) {
EnElforg_SpawnSparkles(this, play, 10);
- this->actor.home.rot.x--;
+ STRAY_FAIRY_SPARKLE_COUNT(&this->actor)--;
}
Actor_SetScale(&this->actor, this->actor.scale.x * 0.9f);
@@ -383,22 +384,24 @@ void EnElforg_CirclePlayer(EnElforg* this, PlayState* play) {
s32 pad;
Actor* playerActor = &GET_PLAYER(play)->actor;
Player* player = GET_PLAYER(play);
- f32 distanceFromPlayer;
+ f32 orbitRadius;
if (GET_PLAYER_FORM == PLAYER_FORM_GORON) {
- distanceFromPlayer = 40.0f;
+ orbitRadius = 40.0f;
} else {
- distanceFromPlayer = 20.0f;
+ orbitRadius = 20.0f;
}
- this->actor.world.pos.x = (Math_SinS(this->timer * 0x1000) * distanceFromPlayer) + playerActor->world.pos.x;
- this->actor.world.pos.z = (Math_CosS(this->timer * 0x1000) * distanceFromPlayer) + playerActor->world.pos.z;
+ this->actor.world.pos.x = (Math_SinS(this->timer * 0x1000) * orbitRadius) + playerActor->world.pos.x;
+ this->actor.world.pos.z = (Math_CosS(this->timer * 0x1000) * orbitRadius) + playerActor->world.pos.z;
this->actor.world.pos.y = player->bodyPartsPos[PLAYER_BODYPART_WAIST].y;
+
EnElforg_SpawnSparkles(this, play, 16);
}
void EnElforg_FairyCollected(EnElforg* this, PlayState* play) {
EnElforg_CirclePlayer(this, play);
+
if (this->timer > 80) {
Actor_Kill(&this->actor);
return;
@@ -424,8 +427,10 @@ void EnElforg_ClockTownFairyCollected(EnElforg* this, PlayState* play) {
Player* player = GET_PLAYER(play);
EnElforg_CirclePlayer(this, play);
+
player->actor.freezeTimer = 100;
player->stateFlags1 |= PLAYER_STATE1_20000000;
+
if (Actor_TextboxIsClosing(&this->actor, play)) {
player->actor.freezeTimer = 0;
player->stateFlags1 &= ~PLAYER_STATE1_20000000;
@@ -451,6 +456,7 @@ void EnElforg_FreeFloating(EnElforg* this, PlayState* play) {
Player* player = GET_PLAYER(play);
SkelAnime_Update(&this->skelAnime);
+
if (Player_GetMask(play) == PLAYER_MASK_GREAT_FAIRY) {
pos = player->bodyPartsPos[PLAYER_BODYPART_WAIST];
this->targetSpeedXZ = 5.0f;
@@ -461,10 +467,12 @@ void EnElforg_FreeFloating(EnElforg* this, PlayState* play) {
}
scaledYDistance = this->actor.playerHeightRel - (this->actor.shape.yOffset * this->actor.scale.y);
+
if (!Player_InCsMode(play)) {
if ((this->actor.xzDistToPlayer < 30.0f) && (scaledYDistance < 12.0f) && (scaledYDistance > -68.0f)) {
EnElforg_SetupFairyCollected(this, play);
Health_ChangeBy(play, 0x30);
+
switch (STRAY_FAIRY_TYPE(&this->actor)) {
case STRAY_FAIRY_TYPE_COLLECTIBLE:
Flags_SetCollectible(play, STRAY_FAIRY_FLAG(&this->actor));
@@ -493,7 +501,8 @@ void EnElforg_FreeFloating(EnElforg* this, PlayState* play) {
gSaveContext.save.saveInfo.inventory.strayFairies[gSaveContext.dungeonIndex]++;
// You found a Stray Fairy!
Message_StartTextbox(play, 0x11, NULL);
- if (gSaveContext.save.saveInfo.inventory.strayFairies[(void)0, gSaveContext.dungeonIndex] >= 15) {
+ if (gSaveContext.save.saveInfo.inventory.strayFairies[(void)0, gSaveContext.dungeonIndex] >=
+ STRAY_FAIRY_SCATTERED_TOTAL) {
Audio_PlayFanfare(NA_BGM_GET_ITEM | 0x900);
}
}
@@ -502,6 +511,7 @@ void EnElforg_FreeFloating(EnElforg* this, PlayState* play) {
Actor_UpdateBgCheckInfo(play, &this->actor, 20.0f, 20.0f, 20.0f,
UPDBGCHECKINFO_FLAG_1 | UPDBGCHECKINFO_FLAG_2 | UPDBGCHECKINFO_FLAG_4);
func_80ACCBB8(this, play);
+
if (Player_GetMask(play) == PLAYER_MASK_GREAT_FAIRY) {
if (!(this->strayFairyFlags & STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED)) {
Audio_PlaySfx(NA_SE_SY_FAIRY_MASK_SUCCESS);
@@ -627,6 +637,7 @@ void EnElforg_Draw(Actor* thisx, PlayState* play) {
OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL25_Xlu(play->state.gfxCtx);
+
switch (this->area) {
case STRAY_FAIRY_AREA_WOODFALL:
AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyWoodfallTexAnim));
@@ -644,7 +655,7 @@ void EnElforg_Draw(Actor* thisx, PlayState* play) {
AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyStoneTowerTexAnim));
break;
- default:
+ default: // STRAY_FAIRY_AREA_CLOCK_TOWN
AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyClockTownTexAnim));
break;
}
diff --git a/src/overlays/actors/ovl_En_Elforg/z_en_elforg.h b/src/overlays/actors/ovl_En_Elforg/z_en_elforg.h
index 798982b09a..7bb8672b12 100644
--- a/src/overlays/actors/ovl_En_Elforg/z_en_elforg.h
+++ b/src/overlays/actors/ovl_En_Elforg/z_en_elforg.h
@@ -2,36 +2,41 @@
#define Z_EN_ELFORG_H
#include "global.h"
+#include "overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#define STRAY_FAIRY_TYPE(thisx) ((thisx)->params & 0xF)
#define STRAY_FAIRY_GET_NON_DUNGEON_AREA(thisx) (((thisx)->params & 0x1C0) >> 6)
#define STRAY_FAIRY_FLAG(thisx) (((thisx)->params & 0xFE00) >> 9)
-#define STRAY_FAIRY_PARAMS(flag, nonDungeonArea, type) (((flag & 0x7F) << 9) | ((nonDungeonArea & 7) << 6) | (type & 0xF))
+#define STRAY_FAIRY_SPARKLE_COUNT(thisx) ((thisx)->home.rot.x)
+
+//! @note `nonDungeonArea` does not always use the enum
+#define STRAY_FAIRY_PARAMS(flag, nonDungeonArea, type) ((((flag) & 0x7F) << 9) | (((nonDungeonArea) & 7) << 6) | ((type) & 0xF))
#define STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME (1 << 0)
#define STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS (1 << 1)
#define STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN (1 << 2)
#define STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED (1 << 3)
-typedef enum {
- /* 0 */ STRAY_FAIRY_TYPE_FREE_FLOATING, // The ones just floating around
- /* 1 */ STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN, // The ones already present when you enter a Fairy Fountain
- /* 2 */ STRAY_FAIRY_TYPE_BUBBLE, // The ones trapped in bubbles
- /* 3 */ STRAY_FAIRY_TYPE_CLOCK_TOWN, // The free-floating Stray Fairies in Clock Town
- /* 4 */ STRAY_FAIRY_TYPE_ENEMY, // The ones trapped inside enemies
- /* 5 */ STRAY_FAIRY_TYPE_COLLIDER, // Unused in retail. The fairy is hidden until the collider is hit
- /* 6 */ STRAY_FAIRY_TYPE_CHEST, // The ones in treasure chests
- /* 7 */ STRAY_FAIRY_TYPE_COLLECTIBLE, // The ones in boxes, pots, beehives, etc.
- /* 8 */ STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN // The ones you "turn in" by walking into a Fairy Fountain
+typedef enum StrayFairyType {
+ /* 0 */ STRAY_FAIRY_TYPE_FREE_FLOATING, // The ones just floating around
+ /* 1 */ STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN, // The ones already present when you enter a Fairy Fountain
+ /* 2 */ STRAY_FAIRY_TYPE_BUBBLE, // The ones trapped in bubbles
+ /* 3 */ STRAY_FAIRY_TYPE_CLOCK_TOWN, // The free-floating Stray Fairies in Clock Town
+ /* 4 */ STRAY_FAIRY_TYPE_ENEMY, // The ones trapped inside enemies
+ /* 5 */ STRAY_FAIRY_TYPE_COLLIDER, // Unused in retail. The fairy is hidden until the collider is hit
+ /* 6 */ STRAY_FAIRY_TYPE_CHEST, // The ones in treasure chests
+ /* 7 */ STRAY_FAIRY_TYPE_COLLECTIBLE, // The ones in boxes, pots, beehives, etc.
+ /* 8 */ STRAY_FAIRY_TYPE_RETURNING_TO_FOUNTAIN // The ones you "turn in" by walking into a Fairy Fountain
} StrayFairyType;
-typedef enum {
- /* 0 */ STRAY_FAIRY_AREA_CLOCK_TOWN,
- /* 1 */ STRAY_FAIRY_AREA_WOODFALL,
- /* 2 */ STRAY_FAIRY_AREA_SNOWHEAD,
- /* 3 */ STRAY_FAIRY_AREA_GREAT_BAY,
- /* 4 */ STRAY_FAIRY_AREA_STONE_TOWER,
+// Corresponds to the Great Fairy types
+typedef enum StrayFairyArea {
+ /* 0 */ STRAY_FAIRY_AREA_CLOCK_TOWN = GREAT_FAIRY_TYPE_MAGIC,
+ /* 1 */ STRAY_FAIRY_AREA_WOODFALL = GREAT_FAIRY_TYPE_POWER,
+ /* 2 */ STRAY_FAIRY_AREA_SNOWHEAD = GREAT_FAIRY_TYPE_WISDOM,
+ /* 3 */ STRAY_FAIRY_AREA_GREAT_BAY = GREAT_FAIRY_TYPE_COURAGE,
+ /* 4 */ STRAY_FAIRY_AREA_STONE_TOWER = GREAT_FAIRY_TYPE_KINDNESS,
/* 5 */ STRAY_FAIRY_AREA_MAX
} StrayFairyArea;
diff --git a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c
index d6f34a256b..b09f8f54d5 100644
--- a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c
+++ b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c
@@ -143,7 +143,7 @@ void EnMThunder_Init(Actor* thisx, PlayState* play) {
player->stateFlags2 &= ~PLAYER_STATE2_20000;
this->isCharging = false;
- if (CHECK_WEEKEVENTREG(WEEKEVENTREG_23_02)) {
+ if (CHECK_WEEKEVENTREG(WEEKEVENTREG_OBTAINED_GREAT_SPIN_ATTACK)) {
player->unk_B08 = 1.0f;
this->collider.info.toucher.damage = sDamages[this->type + ENMTHUNDER_TYPE_MAX];
this->subtype = ENMTHUNDER_SUBTYPE_SPIN_GREAT;
diff --git a/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.c b/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.c
index aca30fe926..cd86326595 100644
--- a/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.c
+++ b/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.c
@@ -255,7 +255,7 @@ void func_80A1BA44(ObjFlowerpot* this, PlayState* play) {
}
EffectSsKakera_Spawn(play, &spC4, &spB8, &spC4, -600, phi_s0, 30, 0, 0, (Rand_ZeroOne() * 12.0f) + 16.6f,
- phi_s1, 0, 35, -1, ACTOR_DEMO_GETITEM, object_flowerpot_DL_0015B0);
+ phi_s1, 0, 35, -1, OBJECT_FLOWERPOT, object_flowerpot_DL_0015B0);
}
spD0.y += 20.0f;
@@ -298,7 +298,7 @@ void func_80A1BD80(ObjFlowerpot* this, PlayState* play) {
}
EffectSsKakera_Spawn(play, &spBC, &spB0, &spBC, -240, phi_s0, 40, 0, 0, (Rand_ZeroOne() * 20.0f) + 10.6f, 0, 0,
- 42, -1, ACTOR_DEMO_GETITEM, object_flowerpot_DL_0015B0);
+ 42, -1, OBJECT_FLOWERPOT, object_flowerpot_DL_0015B0);
}
spBC.y = this->actor.world.pos.y + this->actor.depthInWater;
@@ -338,7 +338,7 @@ void func_80A1C0FC(ObjFlowerpot* this, PlayState* play) {
Math_Vec3f_Sum(&spB8, &spC4, &spB8);
EffectSsKakera_Spawn(play, &spB8, &spAC, &spB8, -100, 64, 40, 0, 0, (Rand_ZeroOne() * 16.0f) + 14.0f, 0, 0, 80,
- -1, ACTOR_DEMO_GETITEM, object_flowerpot_DL_0014F0);
+ -1, OBJECT_FLOWERPOT, object_flowerpot_DL_0014F0);
}
}
@@ -365,7 +365,7 @@ void func_80A1C328(ObjFlowerpot* this, PlayState* play) {
Math_Vec3f_Sum(&spB8, &spC4, &spB8);
EffectSsKakera_Spawn(play, &spB8, &spAC, &spB8, -80, 64, 44, 0, 0, (Rand_ZeroOne() * 16.0f) + 14.0f, 0, 0, 80,
- -1, ACTOR_DEMO_GETITEM, object_flowerpot_DL_0014F0);
+ -1, OBJECT_FLOWERPOT, object_flowerpot_DL_0014F0);
}
}
diff --git a/src/overlays/actors/ovl_Obj_Lightblock/z_obj_lightblock.c b/src/overlays/actors/ovl_Obj_Lightblock/z_obj_lightblock.c
index 6a6937e7e4..f8ee482df0 100644
--- a/src/overlays/actors/ovl_Obj_Lightblock/z_obj_lightblock.c
+++ b/src/overlays/actors/ovl_Obj_Lightblock/z_obj_lightblock.c
@@ -5,6 +5,7 @@
*/
#include "z_obj_lightblock.h"
+#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
#include "objects/object_lightblock/object_lightblock.h"
#define FLAGS 0x00000000
@@ -15,12 +16,12 @@ void ObjLightblock_Init(Actor* thisx, PlayState* play);
void ObjLightblock_Destroy(Actor* thisx, PlayState* play);
void ObjLightblock_Update(Actor* thisx, PlayState* play);
void ObjLightblock_Draw(Actor* thisx, PlayState* play);
-void func_80AF3AC8(ObjLightblock* this);
-void func_80AF3ADC(ObjLightblock* this, PlayState* play);
-void func_80AF3B8C(ObjLightblock* this);
-void func_80AF3BA0(ObjLightblock* this, PlayState* play);
-void func_80AF3C18(ObjLightblock* this);
-void func_80AF3C34(ObjLightblock* this, PlayState* play);
+void ObjLightblock_SetupWait(ObjLightblock* this);
+void ObjLightblock_Wait(ObjLightblock* this, PlayState* play);
+void ObjLightblock_SetupPlayCutscene(ObjLightblock* this);
+void ObjLightblock_PlayCutscene(ObjLightblock* this, PlayState* play);
+void ObjLightblock_SetupFadeAway(ObjLightblock* this);
+void ObjLightblock_FadeAway(ObjLightblock* this, PlayState* play);
ActorInit Obj_Lightblock_InitVars = {
ACTOR_OBJ_LIGHTBLOCK,
@@ -54,17 +55,17 @@ static ColliderCylinderInit sCylinderInit = {
{ 84, 120, 0, { 0, 0, 0 } },
};
-typedef struct {
+typedef struct LightblockTypeVars {
/* 0x0 */ f32 scale;
/* 0x4 */ s16 radius;
/* 0x6 */ s16 height;
/* 0x8 */ s16 yShift;
- /* 0xC */ s32 params;
+ /* 0xC */ s32 effectParams;
} LightblockTypeVars; // size = 0x10
static LightblockTypeVars sLightblockTypeVars[] = {
- { 0.1f, 76, 80, 19, 2 },
- { (1.0f / 6), 126, 144, 19, 3 },
+ { 0.1f, 76, 80, 19, DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_LARGE },
+ { (1.0f / 6.0f), 126, 144, 19, DEMO_EFFECT_TIMEWARP_LIGHTBLOCK_VERY_LARGE },
};
static InitChainEntry sInitChain[] = {
@@ -76,11 +77,11 @@ static InitChainEntry sInitChain[] = {
extern Gfx D_801AEF88[];
extern Gfx D_801AEFA0[];
-void func_80AF3910(ObjLightblock* this, PlayState* play) {
+void ObjLightblock_SpawnEffect(ObjLightblock* this, PlayState* play) {
LightblockTypeVars* typeVars = &sLightblockTypeVars[LIGHTBLOCK_TYPE(&this->dyna.actor)];
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y,
- this->dyna.actor.world.pos.z, 0, 0, 0, typeVars->params);
+ this->dyna.actor.world.pos.z, 0, 0, 0, typeVars->effectParams);
}
void ObjLightblock_Init(Actor* thisx, PlayState* play) {
@@ -104,7 +105,7 @@ void ObjLightblock_Init(Actor* thisx, PlayState* play) {
this->collider.dim.height = typeVars->height;
this->collider.dim.yShift = typeVars->yShift;
this->alpha = 255;
- func_80AF3AC8(this);
+ ObjLightblock_SetupWait(this);
}
void ObjLightblock_Destroy(Actor* thisx, PlayState* play) {
@@ -114,11 +115,14 @@ void ObjLightblock_Destroy(Actor* thisx, PlayState* play) {
Collider_DestroyCylinder(play, &this->collider);
}
-void func_80AF3AC8(ObjLightblock* this) {
- this->actionFunc = func_80AF3ADC;
+void ObjLightblock_SetupWait(ObjLightblock* this) {
+ this->actionFunc = ObjLightblock_Wait;
}
-void func_80AF3ADC(ObjLightblock* this, PlayState* play) {
+/**
+ * Wait for a single collision from a Light Arrow or 8 frames of Mirror Shield ray collision.
+ */
+void ObjLightblock_Wait(ObjLightblock* this, PlayState* play) {
if (this->collider.base.acFlags & AC_HIT) {
this->collider.base.acFlags &= ~AC_HIT;
// light arrows
@@ -135,39 +139,36 @@ void func_80AF3ADC(ObjLightblock* this, PlayState* play) {
if (this->collisionCounter >= 8) {
CutsceneManager_Queue(this->dyna.actor.csId);
- func_80AF3B8C(this);
+ ObjLightblock_SetupPlayCutscene(this);
} else {
CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base);
}
}
-void func_80AF3B8C(ObjLightblock* this) {
- this->actionFunc = func_80AF3BA0;
+void ObjLightblock_SetupPlayCutscene(ObjLightblock* this) {
+ this->actionFunc = ObjLightblock_PlayCutscene;
}
-void func_80AF3BA0(ObjLightblock* this, PlayState* play) {
+void ObjLightblock_PlayCutscene(ObjLightblock* this, PlayState* play) {
if (CutsceneManager_IsNext(this->dyna.actor.csId)) {
CutsceneManager_StartWithPlayerCs(this->dyna.actor.csId, &this->dyna.actor);
Flags_SetSwitch(play, LIGHTBLOCK_DESTROYED(&this->dyna.actor));
- func_80AF3910(this, play);
- func_80AF3C18(this);
+ ObjLightblock_SpawnEffect(this, play);
+ ObjLightblock_SetupFadeAway(this);
} else {
CutsceneManager_Queue(this->dyna.actor.csId);
}
}
-void func_80AF3C18(ObjLightblock* this) {
+void ObjLightblock_SetupFadeAway(ObjLightblock* this) {
this->timer = 80;
- this->actionFunc = func_80AF3C34;
+ this->actionFunc = ObjLightblock_FadeAway;
}
-void func_80AF3C34(ObjLightblock* this, PlayState* play) {
- s8 csId;
-
+void ObjLightblock_FadeAway(ObjLightblock* this, PlayState* play) {
this->timer--;
if (this->timer <= 0) {
- csId = this->dyna.actor.csId;
- CutsceneManager_Stop(csId);
+ CutsceneManager_Stop(this->dyna.actor.csId);
Actor_Kill(&this->dyna.actor);
return;
}
diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c
index d01dbd3be9..07e6915919 100644
--- a/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/src/overlays/actors/ovl_player_actor/z_player.c
@@ -10374,7 +10374,7 @@ void func_80840EC0(Player* this, PlayState* play) {
// Spin attack size
void func_80840F34(Player* this) {
- Math_StepToF(&this->unk_B08, (CHECK_WEEKEVENTREG(WEEKEVENTREG_23_02)) ? 1.0f : 0.5f, 0.02f);
+ Math_StepToF(&this->unk_B08, CHECK_WEEKEVENTREG(WEEKEVENTREG_OBTAINED_GREAT_SPIN_ATTACK) ? 1.0f : 0.5f, 0.02f);
}
s32 func_80840F90(PlayState* play, Player* this, CsCmdActorCue* cue, f32 arg3, s16 arg4, s32 arg5) {
diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_map.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_map.c
index b4ed531f82..ec1ca83ec9 100644
--- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_map.c
+++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_map.c
@@ -19,7 +19,7 @@ void KaleidoScope_DrawDungeonStrayFairyCount(PlayState* play) {
OPEN_DISPS(play->state.gfxCtx);
// Get digits for max number of stray fairies
- counterDigits[1] = 15;
+ counterDigits[1] = STRAY_FAIRY_SCATTERED_TOTAL;
counterDigits[0] = counterDigits[1] / 10;
counterDigits[1] -= (s16)(counterDigits[0] * 10);
diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt
index c1137d3b22..8a60d1f667 100644
--- a/tools/disasm/functions.txt
+++ b/tools/disasm/functions.txt
@@ -6263,17 +6263,17 @@
0x808CD238:("EnVm_Draw",),
0x808CD740:("DemoEffect_Init",),
0x808CD8E8:("DemoEffect_Destroy",),
- 0x808CD940:("func_808CD940",),
- 0x808CD998:("func_808CD998",),
- 0x808CDAD0:("func_808CDAD0",),
- 0x808CDBDC:("func_808CDBDC",),
- 0x808CDCEC:("func_808CDCEC",),
- 0x808CDD70:("func_808CDD70",),
- 0x808CDDE0:("func_808CDDE0",),
+ 0x808CD940:("DemoEffect_WaitForObject",),
+ 0x808CD998:("DemoEffect_SetupTimewarp",),
+ 0x808CDAD0:("DemoEffect_SetPerVertexAlpha",),
+ 0x808CDBDC:("DemoEffect_FinishTimewarp",),
+ 0x808CDCEC:("DemoEffect_StartTimewarp",),
+ 0x808CDD70:("DemoEffect_ShrinkLight",),
+ 0x808CDDE0:("DemoEffect_ExpandLight",),
0x808CDE54:("DemoEffect_Update",),
- 0x808CDE78:("func_808CDE78",),
- 0x808CDFF8:("func_808CDFF8",),
- 0x808CE078:("func_808CE078",),
+ 0x808CDE78:("DemoEffect_OverrideLimbDrawTimewarp",),
+ 0x808CDFF8:("DemoEffect_DrawTimewarp",),
+ 0x808CE078:("DemoEffect_DrawLight",),
0x808CE450:("DemoKankyo_SetupAction",),
0x808CE45C:("func_808CE45C",),
0x808CF06C:("func_808CF06C",),
@@ -9573,9 +9573,9 @@
0x80A07740:("func_80A07740",),
0x80A0A8A0:("BgDyYoseizo_Init",),
0x80A0A95C:("BgDyYoseizo_Destroy",),
- 0x80A0A96C:("func_80A0A96C",),
- 0x80A0A9E4:("func_80A0A9E4",),
- 0x80A0AA40:("func_80A0AA40",),
+ 0x80A0A96C:("BgDyYoseizo_UpdateEyes",),
+ 0x80A0A9E4:("BgDyYoseizo_Bob",),
+ 0x80A0AA40:("BgDyYoseizo_SpawnEffects",),
0x80A0AD50:("func_80A0AD50",),
0x80A0AE1C:("func_80A0AE1C",),
0x80A0AFDC:("func_80A0AFDC",),
@@ -9587,14 +9587,14 @@
0x80A0B5F0:("func_80A0B5F0",),
0x80A0B75C:("func_80A0B75C",),
0x80A0B834:("func_80A0B834",),
- 0x80A0B8CC:("func_80A0B8CC",),
+ 0x80A0B8CC:("BgDyYoseizo_TrainPlayer",),
0x80A0BB08:("func_80A0BB08",),
0x80A0BC84:("BgDyYoseizo_Update",),
- 0x80A0BCD8:("func_80A0BCD8",),
- 0x80A0BD40:("func_80A0BD40",),
- 0x80A0BE60:("func_80A0BE60",),
- 0x80A0BF70:("func_80A0BF70",),
- 0x80A0C270:("func_80A0C270",),
+ 0x80A0BCD8:("BgDyYoseizo_OverrideLimbDraw",),
+ 0x80A0BD40:("BgDyYoseizo_Draw",),
+ 0x80A0BE60:("BgDyYoseizo_SpawnEffect",),
+ 0x80A0BF70:("BgDyYoseizo_UpdateEffects",),
+ 0x80A0C270:("BgDyYoseizo_DrawEffects",),
0x80A0C780:("EnBoj05_Init",),
0x80A0C790:("EnBoj05_Destroy",),
0x80A0C7A0:("EnBoj05_Update",),
@@ -10266,16 +10266,16 @@
0x80A38FB4:("EnRu_OverrideLimbdraw",),
0x80A390F8:("EnRu_PostLimbdraw",),
0x80A39204:("EnRu_Draw",),
- 0x80A396B0:("func_80A396B0",),
+ 0x80A396B0:("EnElfgrp_SetCutscene",),
0x80A3970C:("EnElfgrp_Init",),
0x80A39BC0:("EnElfgrp_Destroy",),
- 0x80A39BD0:("func_80A39BD0",),
- 0x80A39C1C:("func_80A39C1C",),
- 0x80A39CD4:("func_80A39CD4",),
- 0x80A39DC8:("func_80A39DC8",),
- 0x80A39F50:("func_80A39F50",),
- 0x80A39FBC:("func_80A39FBC",),
- 0x80A3A044:("func_80A3A044",),
+ 0x80A39BD0:("EnElfgrp_GetHeldFairiesCount",),
+ 0x80A39C1C:("EnElfgrp_GetFountainFairiesCount",),
+ 0x80A39CD4:("EnElfgrp_SetFountainFairiesCount",),
+ 0x80A39DC8:("EnElfgrp_SpawnStrayFairies",),
+ 0x80A39F50:("EnElfgrp_SummonStrayFairies",),
+ 0x80A39FBC:("EnElfgrp_SpinStrayFairies",),
+ 0x80A3A044:("EnElfgrp_VanishStrayFairies",),
0x80A3A0AC:("func_80A3A0AC",),
0x80A3A0F4:("func_80A3A0F4",),
0x80A3A210:("func_80A3A210",),
@@ -10284,8 +10284,8 @@
0x80A3A484:("func_80A3A484",),
0x80A3A4AC:("func_80A3A4AC",),
0x80A3A520:("func_80A3A520",),
- 0x80A3A600:("func_80A3A600",),
- 0x80A3A610:("func_80A3A610",),
+ 0x80A3A600:("EnElfgrp_DoNothing",),
+ 0x80A3A610:("EnElfgrp_HealPlayer",),
0x80A3A6F4:("func_80A3A6F4",),
0x80A3A77C:("func_80A3A77C",),
0x80A3A7FC:("func_80A3A7FC",),
@@ -10546,8 +10546,8 @@
0x80A4F4C8:("func_80A4F4C8",),
0x80A4FA40:("DemoGetitem_Init",),
0x80A4FB00:("DemoGetitem_Destroy",),
- 0x80A4FB10:("func_80A4FB10",),
- 0x80A4FB68:("func_80A4FB68",),
+ 0x80A4FB10:("DemoGetitem_Wait",),
+ 0x80A4FB68:("DemoGetitem_PerformCutsceneActions",),
0x80A4FCCC:("DemoGetitem_Update",),
0x80A4FCF0:("DemoGetitem_Draw",),
0x80A4FDD0:("func_80A4FDD0",),
@@ -10752,8 +10752,8 @@
0x80A61040:("BgSpoutFire_Draw",),
0x80A612B0:("EnDyExtra_Destroy",),
0x80A612C0:("EnDyExtra_Init",),
- 0x80A61334:("func_80A61334",),
- 0x80A613C8:("func_80A613C8",),
+ 0x80A61334:("EnDyExtra_WaitForTrigger",),
+ 0x80A613C8:("EnDyExtra_Fall",),
0x80A61470:("EnDyExtra_Update",),
0x80A614C4:("EnDyExtra_Draw",),
0x80A61810:("EnBal_Init",),
@@ -12656,15 +12656,15 @@
0x80AF3144:("EnTest7_Update",),
0x80AF31D0:("func_80AF31D0",),
0x80AF3248:("EnTest7_Draw",),
- 0x80AF3910:("func_80AF3910",),
+ 0x80AF3910:("ObjLightblock_SpawnEffect",),
0x80AF397C:("ObjLightblock_Init",),
0x80AF3A80:("ObjLightblock_Destroy",),
- 0x80AF3AC8:("func_80AF3AC8",),
- 0x80AF3ADC:("func_80AF3ADC",),
- 0x80AF3B8C:("func_80AF3B8C",),
- 0x80AF3BA0:("func_80AF3BA0",),
- 0x80AF3C18:("func_80AF3C18",),
- 0x80AF3C34:("func_80AF3C34",),
+ 0x80AF3AC8:("ObjLightblock_SetupWait",),
+ 0x80AF3ADC:("ObjLightblock_Wait",),
+ 0x80AF3B8C:("ObjLightblock_SetupPlayCutscene",),
+ 0x80AF3BA0:("ObjLightblock_PlayCutscene",),
+ 0x80AF3C18:("ObjLightblock_SetupFadeAway",),
+ 0x80AF3C34:("ObjLightblock_FadeAway",),
0x80AF3CC0:("ObjLightblock_Update",),
0x80AF3CE4:("ObjLightblock_Draw",),
0x80AF3F70:("func_80AF3F70",),
diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt
index 417e27b770..5aaa2f1d0b 100644
--- a/tools/disasm/variables.txt
+++ b/tools/disasm/variables.txt
@@ -10574,27 +10574,11 @@
0x80A0A88C:("D_80A0A88C","UNK_TYPE4","",0x4),
0x80A0A890:("D_80A0A890","UNK_TYPE4","",0x4),
0x80A0C4A0:("Bg_Dy_Yoseizo_InitVars","UNK_TYPE1","",0x1),
- 0x80A0C4C0:("D_80A0C4C0","UNK_TYPE4","",0x4),
- 0x80A0C4C4:("D_80A0C4C4","UNK_TYPE4","",0x4),
- 0x80A0C4C8:("D_80A0C4C8","UNK_TYPE4","",0x4),
- 0x80A0C4CC:("D_80A0C4CC","UNK_TYPE4","",0x4),
- 0x80A0C4D0:("D_80A0C4D0","UNK_TYPE4","",0x4),
- 0x80A0C4D8:("D_80A0C4D8","UNK_TYPE4","",0x4),
- 0x80A0C4DC:("D_80A0C4DC","UNK_TYPE4","",0x4),
- 0x80A0C4E0:("D_80A0C4E0","UNK_TYPE4","",0x4),
- 0x80A0C4E4:("D_80A0C4E4","UNK_TYPE1","",0x1),
- 0x80A0C4F8:("D_80A0C4F8","UNK_TYPE1","",0x1),
- 0x80A0C50C:("D_80A0C50C","UNK_TYPE1","",0x1),
- 0x80A0C514:("D_80A0C514","UNK_TYPE1","",0x1),
- 0x80A0C540:("D_80A0C540","f32","",0x4),
- 0x80A0C544:("D_80A0C544","f32","",0x4),
- 0x80A0C548:("D_80A0C548","f32","",0x4),
- 0x80A0C54C:("D_80A0C54C","f32","",0x4),
- 0x80A0C550:("D_80A0C550","f32","",0x4),
- 0x80A0C554:("D_80A0C554","f32","",0x4),
- 0x80A0C558:("D_80A0C558","f32","",0x4),
- 0x80A0C55C:("D_80A0C55C","f32","",0x4),
- 0x80A0C560:("D_80A0C560","f32","",0x4),
+ 0x80A0C4C0:("sAnimations","AnimationHeader*","9",0x24),
+ 0x80A0C4E4:("sEffectPrimColors","Color_RGB8","6",0x12),
+ 0x80A0C4F8:("sEffectEnvColors","Color_RGB8","6",0x12),
+ 0x80A0C50C:("sMouthTextures","UNK_TYPE1","2",0x8),
+ 0x80A0C514:("sStretchFactors","f32","8",0x20),
0x80A0C7C0:("En_Boj_05_InitVars","UNK_TYPE1","",0x1),
0x80A10860:("sAnimationsBombShopkeeper","UNK_PTR","",0x4),
0x80A10890:("En_Sob1_InitVars","UNK_TYPE1","",0x1),
diff --git a/tools/weekeventregconvert.py b/tools/weekeventregconvert.py
index 0bde4a5ce9..35757a022f 100755
--- a/tools/weekeventregconvert.py
+++ b/tools/weekeventregconvert.py
@@ -189,7 +189,7 @@ weekEventReg = {
(22 << 8) | 0x40: "WEEKEVENTREG_22_40",
(22 << 8) | 0x80: "WEEKEVENTREG_22_80",
(23 << 8) | 0x01: "WEEKEVENTREG_23_01",
- (23 << 8) | 0x02: "WEEKEVENTREG_23_02",
+ (23 << 8) | 0x02: "WEEKEVENTREG_OBTAINED_GREAT_SPIN_ATTACK",
(23 << 8) | 0x04: "WEEKEVENTREG_23_04",
(23 << 8) | 0x08: "WEEKEVENTREG_23_08",
(23 << 8) | 0x10: "WEEKEVENTREG_23_10",
diff --git a/undefined_syms.txt b/undefined_syms.txt
index 45307fc872..010f94c053 100644
--- a/undefined_syms.txt
+++ b/undefined_syms.txt
@@ -191,14 +191,6 @@ D_050089D0 = 0x050089D0;
D_060002C8 = 0x060002C8;
D_060005C4 = 0x060005C4;
-// ovl_Bg_Dy_Yoseizo
-
-D_06008090 = 0x06008090;
-D_0600D1B0 = 0x0600D1B0;
-D_0600D228 = 0x0600D228;
-D_0601C6F4 = 0x0601C6F4;
-D_0601C8B4 = 0x0601C8B4;
-
// ovl_Bg_Lotus
D_06000A20 = 0x06000A20;