Some minor cleanup involving stray fairies (#949)

* Some minor cleanup involving stray fairies

* Fix build
This commit is contained in:
Tom Overton 2022-07-23 11:17:35 -07:00 committed by GitHub
parent ba8e12a80b
commit fba92d828a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 83 deletions

View File

@ -972,16 +972,16 @@
<TextureAnimation Name="gStrayFairyWoodfallTexAnim" Offset="0x2C908" /> <TextureAnimation Name="gStrayFairyWoodfallTexAnim" Offset="0x2C908" />
<TextureAnimation Name="gStrayFairyGreatBayTexAnim" Offset="0x2C980" /> <TextureAnimation Name="gStrayFairyGreatBayTexAnim" Offset="0x2C980" />
<TextureAnimation Name="gStrayFairyStoneTowerTexAnim" Offset="0x2C9F8" /> <TextureAnimation Name="gStrayFairyStoneTowerTexAnim" Offset="0x2C9F8" />
<Limb Name="gStrayFairyRightFacingHeadLimb" Type="Standard" Offset="0x2CA08" /> <Limb Name="gStrayFairyRightFacingHeadLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_RIGHT_FACING_HEAD" Offset="0x2CA08" />
<Limb Name="gStrayFairyLeftWingLimb" Type="Standard" Offset="0x2CA14" /> <Limb Name="gStrayFairyLeftWingLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_LEFT_WING" Offset="0x2CA14" />
<Limb Name="gStrayFairyRightWingLimb" Type="Standard" Offset="0x2CA20" /> <Limb Name="gStrayFairyRightWingLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_RIGHT_WING" Offset="0x2CA20" />
<Limb Name="gStrayFairyGlowLimb" Type="Standard" Offset="0x2CA2C" /> <Limb Name="gStrayFairyGlowLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_GLOW" Offset="0x2CA2C" />
<Limb Name="gStrayFairyTorsoLimb" Type="Standard" Offset="0x2CA38" /> <Limb Name="gStrayFairyTorsoLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_TORSO" Offset="0x2CA38" />
<Limb Name="gStrayFairyRightArmLimb" Type="Standard" Offset="0x2CA44" /> <Limb Name="gStrayFairyRightArmLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_RIGHT_ARM" Offset="0x2CA44" />
<Limb Name="gStrayFairyPelvisAndLegsLimb" Type="Standard" Offset="0x2CA50" /> <Limb Name="gStrayFairyPelvisAndLegsLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_PELVIS_AND_LEGS" Offset="0x2CA50" />
<Limb Name="gStrayFairyLeftArmLimb" Type="Standard" Offset="0x2CA5C" /> <Limb Name="gStrayFairyLeftArmLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_LEFT_ARM" Offset="0x2CA5C" />
<Limb Name="gStrayFairyLeftFacingHeadLimb" Type="Standard" Offset="0x2CA68" /> <Limb Name="gStrayFairyLeftFacingHeadLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_LEFT_FACING_HEAD" Offset="0x2CA68" />
<Skeleton Name="gStrayFairySkel" Type="Flex" LimbType="Standard" Offset="0x2CA98" /> <Skeleton Name="gStrayFairySkel" Type="Flex" LimbType="Standard" LimbNone="STRAY_FAIRY_LIMB_NONE" LimbMax="STRAY_FAIRY_LIMB_MAX" EnumName="StrayFairyLimbs" Offset="0x2CA98" />
<Texture Name="gameplay_keep_Tex_02CAA8" OutName="tex_02CAA8" Format="i4" Width="16" Height="16" Offset="0x2CAA8" /> <Texture Name="gameplay_keep_Tex_02CAA8" OutName="tex_02CAA8" Format="i4" Width="16" Height="16" Offset="0x2CAA8" />
<Texture Name="gameplay_keep_Tex_02CB30" OutName="tex_02CB30" Format="i8" Width="16" Height="16" Offset="0x2CB30" /> <Texture Name="gameplay_keep_Tex_02CB30" OutName="tex_02CB30" Format="i8" Width="16" Height="16" Offset="0x2CB30" />

View File

@ -1,6 +1,7 @@
#include "global.h" #include "global.h"
#include "objects/gameplay_keep/gameplay_keep.h" #include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_gi_hearts/object_gi_hearts.h" #include "objects/object_gi_hearts/object_gi_hearts.h"
#include "overlays/actors/ovl_En_Elforg/z_en_elforg.h"
#define FLAGS 0x00000000 #define FLAGS 0x00000000
@ -867,8 +868,9 @@ Actor* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, u32 params) {
SoundSource_PlaySfxAtFixedWorldPos(play, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY); SoundSource_PlaySfxAtFixedWorldPos(play, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY);
} }
} else { } else {
spawnedActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELFORG, spawnPos->x, spawnPos->y + 40.0f, spawnedActor =
spawnPos->z, 0, 0, 0, ((((param7F00 >> 8) & 0x7F) & 0x7F) << 9) | 7); 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));
if (param20000 == 0) { if (param20000 == 0) {
if (!Flags_GetCollectible(play, (param7F00 >> 8) & 0x7F)) { if (!Flags_GetCollectible(play, (param7F00 >> 8) & 0x7F)) {
SoundSource_PlaySfxAtFixedWorldPos(play, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY); SoundSource_PlaySfxAtFixedWorldPos(play, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY);
@ -924,8 +926,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, spawnedActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, spawnPos->x, spawnPos->y + 40.0f,
spawnPos->z, 0, 0, 0, ((((param7F00 >> 8) & 0x7F) << 9) & 0xFE00) | 0x102); spawnPos->z, 0, 0, 0, ((((param7F00 >> 8) & 0x7F) << 9) & 0xFE00) | 0x102);
} else { } else {
spawnedActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELFORG, spawnPos->x, spawnPos->y + 40.0f, spawnedActor =
spawnPos->z, 0, 0, 0, ((((param7F00 >> 8) & 0x7F) & 0x7F) << 9) | 7); 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));
} }
if (Flags_GetCollectible(play, (param7F00 >> 8) & 0x7F) == 0) { if (Flags_GetCollectible(play, (param7F00 >> 8) & 0x7F) == 0) {
SoundSource_PlaySfxAtFixedWorldPos(play, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY); SoundSource_PlaySfxAtFixedWorldPos(play, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY);

View File

@ -538,7 +538,7 @@ void EnBox_Open(EnBox* this, PlayState* play) {
Actor_SpawnAsChild(&play->actorCtx, &this->dyna.actor, play, ACTOR_EN_ELFORG, this->dyna.actor.world.pos.x, 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.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, this->dyna.actor.world.rot.y, this->dyna.actor.world.rot.z,
((ENBOX_GET_CHEST_FLAG(&this->dyna.actor) & 0x7F) << 9) | STRAY_FAIRY_TYPE_CHEST); STRAY_FAIRY_PARAMS(ENBOX_GET_CHEST_FLAG(&this->dyna.actor), 0, STRAY_FAIRY_TYPE_CHEST));
} else if (this->movementFlags & ENBOX_MOVE_0x40) { } else if (this->movementFlags & ENBOX_MOVE_0x40) {
this->movementFlags &= ~ENBOX_MOVE_0x40; this->movementFlags &= ~ENBOX_MOVE_0x40;
} }

View File

@ -73,10 +73,10 @@ void EnElfbub_Init(Actor* thisx, PlayState* play) {
Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit); Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
this->actor.colChkInfo.mass = MASS_IMMOVABLE; this->actor.colChkInfo.mass = MASS_IMMOVABLE;
childActor = Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_ELFORG, this->actor.world.pos.x, childActor = Actor_SpawnAsChild(
this->actor.world.pos.y + 12.0f, this->actor.world.pos.z, this->actor.world.rot.x, &play->actorCtx, &this->actor, play, ACTOR_EN_ELFORG, this->actor.world.pos.x, this->actor.world.pos.y + 12.0f,
this->actor.world.rot.y, this->actor.world.rot.z, this->actor.world.pos.z, this->actor.world.rot.x, this->actor.world.rot.y, this->actor.world.rot.z,
((ENELFBUB_GET_SWITCHFLAG(&this->actor) & 0x7F) << 9) | STRAY_FAIRY_TYPE_BUBBLE); STRAY_FAIRY_PARAMS(ENELFBUB_GET_SWITCHFLAG(&this->actor), 0, STRAY_FAIRY_TYPE_BUBBLE));
if (childActor != NULL) { if (childActor != NULL) {
childActor->parent = &this->actor; childActor->parent = &this->actor;
} }

View File

@ -241,7 +241,7 @@ void func_80A39DC8(EnElfgrp* this, PlayState* play, s32 arg2, s32 arg3) {
s32 pad; s32 pad;
s32 i; s32 i;
Actor* elforg; Actor* elforg;
s32 temp; s32 params;
Vec3f sp6C; Vec3f sp6C;
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
@ -252,16 +252,16 @@ void func_80A39DC8(EnElfgrp* this, PlayState* play, s32 arg2, s32 arg3) {
if (arg3 == 0) { if (arg3 == 0) {
sp6C = this->actor.world.pos; sp6C = this->actor.world.pos;
sp6C.y += 20.0f; sp6C.y += 20.0f;
temp = ((this->unk_147 & 7) << 6) | STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN; params = STRAY_FAIRY_PARAMS(0, this->unk_147, STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN);
} else { } else {
sp6C = player->actor.world.pos; sp6C = player->actor.world.pos;
sp6C.y += 20.0f; sp6C.y += 20.0f;
temp = ((this->unk_147 & 7) << 6) | STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN; params = STRAY_FAIRY_PARAMS(0, this->unk_147, STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN);
} }
for (i = 0; i < arg2; i++) { for (i = 0; i < arg2; i++) {
elforg = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELFORG, randPlusMinusPoint5Scaled(20.0f) + sp6C.x, sp6C.y, elforg = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELFORG, randPlusMinusPoint5Scaled(20.0f) + sp6C.x, sp6C.y,
randPlusMinusPoint5Scaled(20.0f) + sp6C.z, 0, 0, 0, temp); randPlusMinusPoint5Scaled(20.0f) + sp6C.z, 0, 0, 0, params);
if (elforg == NULL) { if (elforg == NULL) {
continue; continue;
} }
@ -284,8 +284,8 @@ s32 func_80A39F50(PlayState* play) {
} }
elfOrg = (EnElforg*)itemAction; elfOrg = (EnElforg*)itemAction;
if (!(elfOrg->flags & STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME)) { if (!(elfOrg->strayFairyFlags & STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME)) {
elfOrg->flags |= STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME; elfOrg->strayFairyFlags |= STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME;
} }
itemAction = itemAction->next; itemAction = itemAction->next;
} }
@ -307,8 +307,8 @@ s32 func_80A39FBC(PlayState* play) {
} }
elfOrg = (EnElforg*)itemAction; elfOrg = (EnElforg*)itemAction;
if (!(elfOrg->flags & STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN)) { if (!(elfOrg->strayFairyFlags & STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN)) {
elfOrg->flags |= STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN; elfOrg->strayFairyFlags |= STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN;
if (phi_v1 >= 100) { if (phi_v1 >= 100) {
return phi_v1; return phi_v1;
} }
@ -336,7 +336,7 @@ void func_80A3A044(PlayState* play) {
elfOrg = (EnElforg*)itemAction; elfOrg = (EnElforg*)itemAction;
elfOrg->actor.home.rot.x = 0x14; elfOrg->actor.home.rot.x = 0x14;
elfOrg->flags |= STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS; elfOrg->strayFairyFlags |= STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS;
itemAction = itemAction->next; itemAction = itemAction->next;
} }

View File

@ -5,7 +5,6 @@
*/ */
#include "z_en_elforg.h" #include "z_en_elforg.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#define FLAGS (ACTOR_FLAG_10) #define FLAGS (ACTOR_FLAG_10)
@ -70,34 +69,37 @@ void EnElforg_Init(Actor* thisx, PlayState* play) {
s32 pad; s32 pad;
EnElforg* this = THIS; EnElforg* this = THIS;
Actor_SetScale(&this->actor, 0.01f); Actor_SetScale(thisx, 0.01f);
this->flags = 0; this->strayFairyFlags = 0;
this->direction = 0; this->direction = 0;
SkelAnime_InitFlex(play, &this->skelAnime, &gStrayFairySkel, &gStrayFairyFlyingAnim, this->jointTable, SkelAnime_InitFlex(play, &this->skelAnime, &gStrayFairySkel, &gStrayFairyFlyingAnim, this->jointTable,
this->jointTable, STRAY_FAIRY_LIMB_MAX); this->jointTable, STRAY_FAIRY_LIMB_MAX);
this->skelAnime.playSpeed = 1.0f; this->skelAnime.playSpeed = 1.0f;
ActorShape_Init(&this->actor.shape, 0.0f, NULL, 0.0f); ActorShape_Init(&thisx->shape, 0.0f, NULL, 0.0f);
this->actor.shape.shadowAlpha = 255; thisx->shape.shadowAlpha = 255;
switch (STRAY_FAIRY_TYPE(&this->actor)) { switch (STRAY_FAIRY_TYPE(thisx)) {
case STRAY_FAIRY_TYPE_CLOCK_TOWN: case STRAY_FAIRY_TYPE_CLOCK_TOWN:
if (gSaveContext.save.weekEventReg[8] & 0x80) { if (gSaveContext.save.weekEventReg[8] & 0x80) {
Actor_MarkForDeath(&this->actor); Actor_MarkForDeath(thisx);
return; return;
} }
break; break;
case STRAY_FAIRY_TYPE_COLLECTIBLE: case STRAY_FAIRY_TYPE_COLLECTIBLE:
if (Flags_GetCollectible(play, STRAY_FAIRY_FLAG(&this->actor))) { if (Flags_GetCollectible(play, STRAY_FAIRY_FLAG(thisx))) {
Actor_MarkForDeath(&this->actor); Actor_MarkForDeath(thisx);
return; return;
} }
break; break;
default: default:
if (Flags_GetSwitch(play, STRAY_FAIRY_FLAG(&this->actor))) { if (Flags_GetSwitch(play, STRAY_FAIRY_FLAG(thisx))) {
Actor_MarkForDeath(&this->actor); Actor_MarkForDeath(thisx);
return; return;
} }
break; break;
case STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN: case STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN:
case STRAY_FAIRY_TYPE_BUBBLE: case STRAY_FAIRY_TYPE_BUBBLE:
case STRAY_FAIRY_TYPE_CHEST: case STRAY_FAIRY_TYPE_CHEST:
@ -108,44 +110,48 @@ void EnElforg_Init(Actor* thisx, PlayState* play) {
if (Map_IsInDungeonOrBossArea(play)) { if (Map_IsInDungeonOrBossArea(play)) {
this->area = gSaveContext.dungeonIndex + STRAY_FAIRY_AREA_WOODFALL; this->area = gSaveContext.dungeonIndex + STRAY_FAIRY_AREA_WOODFALL;
} else { } else {
// Needs to be thisx in order to match
this->area = STRAY_FAIRY_GET_NON_DUNGEON_AREA(thisx); this->area = STRAY_FAIRY_GET_NON_DUNGEON_AREA(thisx);
} }
switch (STRAY_FAIRY_TYPE(&this->actor)) { switch (STRAY_FAIRY_TYPE(thisx)) {
case STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN: case STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN:
EnElforg_InitializeParams(this); EnElforg_InitializeParams(this);
this->actionFunc = EnElforg_FreeFloatingFairyFountain; this->actionFunc = EnElforg_FreeFloatingFairyFountain;
this->targetSpeedXZ = Rand_ZeroFloat(2.0f) + 1.0f; this->targetSpeedXZ = Rand_ZeroFloat(2.0f) + 1.0f;
this->targetDistanceFromHome = Rand_ZeroFloat(100.0f) + 50.0f; this->targetDistanceFromHome = Rand_ZeroFloat(100.0f) + 50.0f;
break; break;
case STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN: case STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN:
EnElforg_InitializeParams(this); EnElforg_InitializeParams(this);
this->actionFunc = EnElforg_TurnInFairy; this->actionFunc = EnElforg_TurnInFairy;
this->secondaryTimer = 60; this->secondaryTimer = 60;
break; break;
case STRAY_FAIRY_TYPE_BUBBLE: case STRAY_FAIRY_TYPE_BUBBLE:
this->timer = 0; this->timer = 0;
this->actionFunc = EnElforg_TrappedByBubble; this->actionFunc = EnElforg_TrappedByBubble;
break; break;
case STRAY_FAIRY_TYPE_ENEMY: case STRAY_FAIRY_TYPE_ENEMY:
this->actionFunc = EnElforg_SetupTrappedByEnemy; this->actionFunc = EnElforg_SetupTrappedByEnemy;
EnElforg_SetupTrappedByEnemy(this, play); EnElforg_SetupTrappedByEnemy(this, play);
this->actor.draw = NULL; thisx->draw = NULL;
break; break;
case STRAY_FAIRY_TYPE_COLLIDER: case STRAY_FAIRY_TYPE_COLLIDER:
this->actionFunc = EnElforg_HiddenByCollider; this->actionFunc = EnElforg_HiddenByCollider;
this->actor.draw = NULL; thisx->draw = NULL;
Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit); Collider_InitAndSetCylinder(play, &this->collider, thisx, &sCylinderInit);
Collider_UpdateCylinder(&this->actor, &this->collider); Collider_UpdateCylinder(thisx, &this->collider);
break; break;
default: default:
EnElforg_InitializeParams(this); EnElforg_InitializeParams(this);
this->actionFunc = EnElforg_FreeFloating; this->actionFunc = EnElforg_FreeFloating;
break; break;
} }
this->actor.shape.rot.y = 0; thisx->shape.rot.y = 0;
} }
void EnElforg_Destroy(Actor* thisx, PlayState* play) { void EnElforg_Destroy(Actor* thisx, PlayState* play) {
@ -216,6 +222,7 @@ void EnElforg_MoveToTargetFairyFountain(EnElforg* this, Vec3f* homePos) {
zDifference = this->actor.world.pos.z - homePos->z; zDifference = this->actor.world.pos.z - homePos->z;
targetAngle = Math_FAtan2F(-zDifference, -xDifference); targetAngle = Math_FAtan2F(-zDifference, -xDifference);
xzDistance = sqrtf(SQ(xDifference) + SQ(zDifference)); xzDistance = sqrtf(SQ(xDifference) + SQ(zDifference));
if ((this->targetDistanceFromHome + 10.0f) < xzDistance) { if ((this->targetDistanceFromHome + 10.0f) < xzDistance) {
angleAdjustment = 0x1000; angleAdjustment = 0x1000;
} else if ((this->targetDistanceFromHome - 10.0f) > xzDistance) { } else if ((this->targetDistanceFromHome - 10.0f) > xzDistance) {
@ -223,6 +230,7 @@ void EnElforg_MoveToTargetFairyFountain(EnElforg* this, Vec3f* homePos) {
} else { } else {
angleAdjustment = 0x4000; angleAdjustment = 0x4000;
} }
targetAngle += angleAdjustment; targetAngle += angleAdjustment;
Math_SmoothStepToS(&this->actor.world.rot.y, targetAngle, 2, 4000, 1000); Math_SmoothStepToS(&this->actor.world.rot.y, targetAngle, 2, 4000, 1000);
EnElforg_ApproachTargetSpeedXZ(this); EnElforg_ApproachTargetSpeedXZ(this);
@ -240,6 +248,7 @@ void EnElforg_MoveToTarget(EnElforg* this, Vec3f* targetPos) {
this->actor.shape.yOffset += 100.0f * Math_SinS(this->timer << 9); this->actor.shape.yOffset += 100.0f * Math_SinS(this->timer << 9);
EnElforg_ApproachTargetYPosition(this, targetPos); EnElforg_ApproachTargetYPosition(this, targetPos);
targetAngle = Math_FAtan2F(-(this->actor.world.pos.z - targetPos->z), -(this->actor.world.pos.x - targetPos->x)); targetAngle = Math_FAtan2F(-(this->actor.world.pos.z - targetPos->z), -(this->actor.world.pos.x - targetPos->x));
if (this->targetSpeedXZ > 2.0f) { if (this->targetSpeedXZ > 2.0f) {
Math_SmoothStepToS(&this->actor.world.rot.y, targetAngle, 2, 0x400, 0x100); Math_SmoothStepToS(&this->actor.world.rot.y, targetAngle, 2, 0x400, 0x100);
} else { } else {
@ -248,6 +257,7 @@ void EnElforg_MoveToTarget(EnElforg* this, Vec3f* targetPos) {
targetAngle += 0x2000; targetAngle += 0x2000;
Math_SmoothStepToS(&this->actor.world.rot.y, targetAngle, 10, 0x200, 0x80); Math_SmoothStepToS(&this->actor.world.rot.y, targetAngle, 10, 0x200, 0x80);
} }
EnElforg_ApproachTargetSpeedXZ(this); EnElforg_ApproachTargetSpeedXZ(this);
Actor_MoveWithGravity(&this->actor); Actor_MoveWithGravity(&this->actor);
} }
@ -258,6 +268,7 @@ void func_80ACCBB8(EnElforg* this, PlayState* play) {
void EnElforg_TrappedByBubble(EnElforg* this, PlayState* play) { void EnElforg_TrappedByBubble(EnElforg* this, PlayState* play) {
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
if ((this->actor.parent == NULL) || (this->actor.parent->update == NULL)) { if ((this->actor.parent == NULL) || (this->actor.parent->update == NULL)) {
EnElforg_InitializeParams(this); EnElforg_InitializeParams(this);
this->actionFunc = EnElforg_FreeFloating; this->actionFunc = EnElforg_FreeFloating;
@ -266,6 +277,7 @@ void EnElforg_TrappedByBubble(EnElforg* this, PlayState* play) {
this->actor.world.pos = this->actor.parent->world.pos; this->actor.world.pos = this->actor.parent->world.pos;
this->actor.world.pos.y += 12.0f; this->actor.world.pos.y += 12.0f;
} }
func_80ACCBB8(this, play); func_80ACCBB8(this, play);
} }
@ -282,10 +294,12 @@ void EnElforg_TurnInFairy(EnElforg* this, PlayState* play) {
this->actor.shape.yOffset *= 0.9f; this->actor.shape.yOffset *= 0.9f;
this->actor.speedXZ = 5.0f; this->actor.speedXZ = 5.0f;
EnElforg_ApproachTargetYPosition(this, &player->bodyPartsPos[0]); EnElforg_ApproachTargetYPosition(this, &player->bodyPartsPos[0]);
xzDistToPlayer = this->actor.xzDistToPlayer; xzDistToPlayer = this->actor.xzDistToPlayer;
if (xzDistToPlayer < 0.0f) { if (xzDistToPlayer < 0.0f) {
xzDistToPlayer = 10.0f; xzDistToPlayer = 10.0f;
} }
newAngle = 0x28000 / xzDistToPlayer; newAngle = 0x28000 / xzDistToPlayer;
Math_SmoothStepToF(&xzDistToPlayer, 40.0f, 0.2f, 100.0f, 1.0f); Math_SmoothStepToF(&xzDistToPlayer, 40.0f, 0.2f, 100.0f, 1.0f);
rotationTemp = this->actor.yawTowardsPlayer - newAngle; rotationTemp = this->actor.yawTowardsPlayer - newAngle;
@ -303,7 +317,7 @@ void EnElforg_TurnInFairy(EnElforg* this, PlayState* play) {
this->targetSpeedXZ = 3.0f; this->targetSpeedXZ = 3.0f;
this->targetDistanceFromHome = 50.0f; this->targetDistanceFromHome = 50.0f;
this->actionFunc = EnElforg_FreeFloatingFairyFountain; this->actionFunc = EnElforg_FreeFloatingFairyFountain;
this->flags &= ~STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN; this->strayFairyFlags &= ~STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN;
} }
} }
@ -313,19 +327,21 @@ void EnElforg_QuicklyCircleFairyFountain(EnElforg* this, PlayState* play) {
if (this->secondaryTimer <= 30) { if (this->secondaryTimer <= 30) {
this->actionFunc = EnElforg_TurnInFairy; this->actionFunc = EnElforg_TurnInFairy;
} }
this->secondaryTimer--; this->secondaryTimer--;
} }
void EnElforg_FreeFloatingFairyFountain(EnElforg* this, PlayState* play) { void EnElforg_FreeFloatingFairyFountain(EnElforg* this, PlayState* play) {
s32 pad; s32 pad;
if (this->flags & STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME) { if (this->strayFairyFlags & STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME) {
// This happens when "turning in" the last batch of Stray Fairies to // This happens when "turning in" the last batch of Stray Fairies to
// a Fairy Fountain. The ones being "turned in" will fly very // a Fairy Fountain. The ones being "turned in" will fly very
// quickly to the center of the fountain. // quickly to the center of the fountain.
if (this->targetSpeedXZ < 8.0f) { if (this->targetSpeedXZ < 8.0f) {
this->targetSpeedXZ += 0.1f; this->targetSpeedXZ += 0.1f;
} }
if (this->targetDistanceFromHome > 0.0f) { if (this->targetDistanceFromHome > 0.0f) {
this->targetDistanceFromHome -= 2.0f; this->targetDistanceFromHome -= 2.0f;
} }
@ -335,22 +351,27 @@ void EnElforg_FreeFloatingFairyFountain(EnElforg* this, PlayState* play) {
} else { } else {
this->targetSpeedXZ = Rand_ZeroFloat(2.0f) + 1.0f; this->targetSpeedXZ = Rand_ZeroFloat(2.0f) + 1.0f;
} }
this->targetDistanceFromHome = Rand_ZeroFloat(100.0f) + 50.0f; this->targetDistanceFromHome = Rand_ZeroFloat(100.0f) + 50.0f;
} }
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
EnElforg_MoveToTargetFairyFountain(this, &this->actor.home.pos); EnElforg_MoveToTargetFairyFountain(this, &this->actor.home.pos);
if (this->flags & STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN) {
if (this->strayFairyFlags & STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN) {
// A small number of fairies will do this when the player walks into // A small number of fairies will do this when the player walks into
// the center of the fountain to be healed. // the center of the fountain to be healed.
this->actionFunc = EnElforg_QuicklyCircleFairyFountain; this->actionFunc = EnElforg_QuicklyCircleFairyFountain;
} }
if (this->flags & STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS) {
if (this->strayFairyFlags & STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS) {
// This happens right before the Great Fairy appears once all // This happens right before the Great Fairy appears once all
// Stray Fairies are saved. // Stray Fairies are saved.
if (this->actor.home.rot.x > 0) { if (this->actor.home.rot.x > 0) {
EnElforg_SpawnSparkles(this, play, 10); EnElforg_SpawnSparkles(this, play, 10);
this->actor.home.rot.x--; this->actor.home.rot.x--;
} }
Actor_SetScale(&this->actor, this->actor.scale.x * 0.9f); Actor_SetScale(&this->actor, this->actor.scale.x * 0.9f);
if (this->actor.scale.x < 0.001f) { if (this->actor.scale.x < 0.001f) {
Actor_MarkForDeath(&this->actor); Actor_MarkForDeath(&this->actor);
@ -369,6 +390,7 @@ void EnElforg_CirclePlayer(EnElforg* this, PlayState* play) {
} else { } else {
distanceFromPlayer = 20.0f; distanceFromPlayer = 20.0f;
} }
this->actor.world.pos.x = (Math_SinS(this->timer << 12) * distanceFromPlayer) + playerActor->world.pos.x; this->actor.world.pos.x = (Math_SinS(this->timer << 12) * distanceFromPlayer) + playerActor->world.pos.x;
this->actor.world.pos.z = (Math_CosS(this->timer << 12) * distanceFromPlayer) + playerActor->world.pos.z; this->actor.world.pos.z = (Math_CosS(this->timer << 12) * distanceFromPlayer) + playerActor->world.pos.z;
this->actor.world.pos.y = player->bodyPartsPos[0].y; this->actor.world.pos.y = player->bodyPartsPos[0].y;
@ -381,6 +403,7 @@ void EnElforg_FairyCollected(EnElforg* this, PlayState* play) {
Actor_MarkForDeath(&this->actor); Actor_MarkForDeath(&this->actor);
return; return;
} }
func_800B9010(&this->actor, NA_SE_PL_CHIBI_FAIRY_HEAL - SFX_FLAG); func_800B9010(&this->actor, NA_SE_PL_CHIBI_FAIRY_HEAL - SFX_FLAG);
} }
@ -445,9 +468,11 @@ void EnElforg_FreeFloating(EnElforg* this, PlayState* play) {
case STRAY_FAIRY_TYPE_COLLECTIBLE: case STRAY_FAIRY_TYPE_COLLECTIBLE:
Flags_SetCollectible(play, STRAY_FAIRY_FLAG(&this->actor)); Flags_SetCollectible(play, STRAY_FAIRY_FLAG(&this->actor));
break; break;
case STRAY_FAIRY_TYPE_CHEST: case STRAY_FAIRY_TYPE_CHEST:
Flags_SetTreasure(play, STRAY_FAIRY_FLAG(&this->actor)); Flags_SetTreasure(play, STRAY_FAIRY_FLAG(&this->actor));
break; break;
default: default:
Flags_SetSwitch(play, STRAY_FAIRY_FLAG(&this->actor)); Flags_SetSwitch(play, STRAY_FAIRY_FLAG(&this->actor));
break; break;
@ -456,6 +481,7 @@ void EnElforg_FreeFloating(EnElforg* this, PlayState* play) {
if (STRAY_FAIRY_TYPE(&this->actor) == STRAY_FAIRY_TYPE_CLOCK_TOWN) { if (STRAY_FAIRY_TYPE(&this->actor) == STRAY_FAIRY_TYPE_CLOCK_TOWN) {
player->actor.freezeTimer = 100; player->actor.freezeTimer = 100;
player->stateFlags1 |= 0x20000000; player->stateFlags1 |= 0x20000000;
// Bring me back to North Clock Town!
Message_StartTextbox(play, 0x579, NULL); Message_StartTextbox(play, 0x579, NULL);
this->actionFunc = EnElforg_ClockTownFairyCollected; this->actionFunc = EnElforg_ClockTownFairyCollected;
ActorCutscene_SetIntentToPlay(0x7C); ActorCutscene_SetIntentToPlay(0x7C);
@ -464,6 +490,7 @@ void EnElforg_FreeFloating(EnElforg* this, PlayState* play) {
if (Map_IsInDungeonOrBossArea(play)) { if (Map_IsInDungeonOrBossArea(play)) {
gSaveContext.save.inventory.strayFairies[gSaveContext.dungeonIndex]++; gSaveContext.save.inventory.strayFairies[gSaveContext.dungeonIndex]++;
// You found a Stray Fairy!
Message_StartTextbox(play, 0x11, NULL); Message_StartTextbox(play, 0x11, NULL);
if (gSaveContext.save.inventory.strayFairies[(void)0, gSaveContext.dungeonIndex] >= 15) { if (gSaveContext.save.inventory.strayFairies[(void)0, gSaveContext.dungeonIndex] >= 15) {
func_801A3098(NA_BGM_GET_ITEM | 0x900); func_801A3098(NA_BGM_GET_ITEM | 0x900);
@ -474,12 +501,13 @@ void EnElforg_FreeFloating(EnElforg* this, PlayState* play) {
Actor_UpdateBgCheckInfo(play, &this->actor, 20.0f, 20.0f, 20.0f, 7); Actor_UpdateBgCheckInfo(play, &this->actor, 20.0f, 20.0f, 20.0f, 7);
func_80ACCBB8(this, play); func_80ACCBB8(this, play);
if (Player_GetMask(play) == PLAYER_MASK_GREAT_FAIRY) { if (Player_GetMask(play) == PLAYER_MASK_GREAT_FAIRY) {
if (!(this->flags & STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED)) { if (!(this->strayFairyFlags & STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED)) {
play_sound(NA_SE_SY_FAIRY_MASK_SUCCESS); play_sound(NA_SE_SY_FAIRY_MASK_SUCCESS);
} }
this->flags |= STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED;
this->strayFairyFlags |= STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED;
} else { } else {
this->flags &= ~STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED; this->strayFairyFlags &= ~STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED;
} }
} }
} }
@ -499,6 +527,7 @@ Actor* EnElforg_GetHoldingEnemy(EnElforg* this, PlayState* play) {
return enemy; return enemy;
} }
} }
return NULL; return NULL;
} }
@ -523,6 +552,7 @@ void EnElforg_TrappedByEnemy(EnElforg* this, PlayState* play) {
this->actor.world.pos.z = posTemp; this->actor.world.pos.z = posTemp;
this->actor.home.pos.z = posTemp; this->actor.home.pos.z = posTemp;
} }
func_80ACCBB8(this, play); func_80ACCBB8(this, play);
} }
@ -546,6 +576,7 @@ void EnElforg_HiddenByCollider(EnElforg* this, PlayState* play) {
} else { } else {
CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base);
} }
func_80ACCBB8(this, play); func_80ACCBB8(this, play);
} }
@ -598,19 +629,24 @@ void EnElforg_Draw(Actor* thisx, PlayState* play) {
case STRAY_FAIRY_AREA_WOODFALL: case STRAY_FAIRY_AREA_WOODFALL:
AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyWoodfallTexAnim)); AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyWoodfallTexAnim));
break; break;
case STRAY_FAIRY_AREA_SNOWHEAD: case STRAY_FAIRY_AREA_SNOWHEAD:
AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairySnowheadTexAnim)); AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairySnowheadTexAnim));
break; break;
case STRAY_FAIRY_AREA_GREAT_BAY: case STRAY_FAIRY_AREA_GREAT_BAY:
AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyGreatBayTexAnim)); AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyGreatBayTexAnim));
break; break;
case STRAY_FAIRY_AREA_STONE_TOWER: case STRAY_FAIRY_AREA_STONE_TOWER:
AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyStoneTowerTexAnim)); AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyStoneTowerTexAnim));
break; break;
default: default:
AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyClockTownTexAnim)); AnimatedMat_Draw(play, Lib_SegmentedToVirtual(gStrayFairyClockTownTexAnim));
break; break;
} }
Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY); Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY);
POLY_XLU_DISP = POLY_XLU_DISP =

View File

@ -2,10 +2,12 @@
#define Z_EN_ELFORG_H #define Z_EN_ELFORG_H
#include "global.h" #include "global.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#define STRAY_FAIRY_TYPE(thisx) ((thisx)->params & 0xF) #define STRAY_FAIRY_TYPE(thisx) ((thisx)->params & 0xF)
#define STRAY_FAIRY_GET_NON_DUNGEON_AREA(thisx) (((thisx)->params & 0x1C0) >> 6) #define STRAY_FAIRY_GET_NON_DUNGEON_AREA(thisx) (((thisx)->params & 0x1C0) >> 6)
#define STRAY_FAIRY_FLAG(thisx) (((thisx)->params & 0xFE00) >> 9) #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_FLAG_MOVES_QUICKLY_TO_HOME (1 << 0) #define STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME (1 << 0)
#define STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS (1 << 1) #define STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS (1 << 1)
@ -13,40 +15,26 @@
#define STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED (1 << 3) #define STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED (1 << 3)
typedef enum { typedef enum {
STRAY_FAIRY_TYPE_FREE_FLOATING, // The ones just floating around /* 0 */ STRAY_FAIRY_TYPE_FREE_FLOATING, // The ones just floating around
STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN, // The ones already present when you enter a Fairy Fountain /* 1 */ STRAY_FAIRY_TYPE_FAIRY_FOUNTAIN, // The ones already present when you enter a Fairy Fountain
STRAY_FAIRY_TYPE_BUBBLE, // The ones trapped in bubbles /* 2 */ STRAY_FAIRY_TYPE_BUBBLE, // The ones trapped in bubbles
STRAY_FAIRY_TYPE_CLOCK_TOWN, // The free-floating Stray Fairies in Clock Town /* 3 */ STRAY_FAIRY_TYPE_CLOCK_TOWN, // The free-floating Stray Fairies in Clock Town
STRAY_FAIRY_TYPE_ENEMY, // The ones trapped inside enemies /* 4 */ STRAY_FAIRY_TYPE_ENEMY, // The ones trapped inside enemies
STRAY_FAIRY_TYPE_COLLIDER, // Unused in retail. The fairy is hidden until the collider is hit /* 5 */ STRAY_FAIRY_TYPE_COLLIDER, // Unused in retail. The fairy is hidden until the collider is hit
STRAY_FAIRY_TYPE_CHEST, // The ones in treasure chests /* 6 */ STRAY_FAIRY_TYPE_CHEST, // The ones in treasure chests
STRAY_FAIRY_TYPE_COLLECTIBLE, // The ones in boxes, pots, beehives, etc. /* 7 */ STRAY_FAIRY_TYPE_COLLECTIBLE, // The ones in boxes, pots, beehives, etc.
STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN // The ones you "turn in" by walking into a Fairy Fountain /* 8 */ STRAY_FAIRY_TYPE_TURN_IN_TO_FAIRY_FOUNTAIN // The ones you "turn in" by walking into a Fairy Fountain
} StrayFairyType; } StrayFairyType;
typedef enum { typedef enum {
STRAY_FAIRY_AREA_CLOCK_TOWN, /* 0 */ STRAY_FAIRY_AREA_CLOCK_TOWN,
STRAY_FAIRY_AREA_WOODFALL, /* 1 */ STRAY_FAIRY_AREA_WOODFALL,
STRAY_FAIRY_AREA_SNOWHEAD, /* 2 */ STRAY_FAIRY_AREA_SNOWHEAD,
STRAY_FAIRY_AREA_GREAT_BAY, /* 3 */ STRAY_FAIRY_AREA_GREAT_BAY,
STRAY_FAIRY_AREA_STONE_TOWER, /* 4 */ STRAY_FAIRY_AREA_STONE_TOWER,
STRAY_FAIRY_AREA_MAX /* 5 */ STRAY_FAIRY_AREA_MAX
} StrayFairyArea; } StrayFairyArea;
typedef enum {
/* 0 */ STRAY_FAIRY_LIMB_NONE,
/* 1 */ STRAY_FAIRY_LIMB_RIGHT_FACING_HEAD,
/* 2 */ STRAY_FAIRY_LIMB_LEFT_WING,
/* 3 */ STRAY_FAIRY_LIMB_RIGHT_WING,
/* 4 */ STRAY_FAIRY_LIMB_GLOW,
/* 5 */ STRAY_FAIRY_LIMB_TORSO,
/* 6 */ STRAY_FAIRY_LIMB_RIGHT_ARM,
/* 7 */ STRAY_FAIRY_LIMB_PELVIS_AND_LEGS,
/* 8 */ STRAY_FAIRY_LIMB_LEFT_ARM,
/* 9 */ STRAY_FAIRY_LIMB_LEFT_FACING_HEAD,
/* 10 */ STRAY_FAIRY_LIMB_MAX,
} StrayFairyLimbs;
struct EnElforg; struct EnElforg;
typedef void (*EnElforgActionFunc)(struct EnElforg*, PlayState*); typedef void (*EnElforgActionFunc)(struct EnElforg*, PlayState*);
@ -57,7 +45,7 @@ typedef struct EnElforg {
/* 0x188 */ Vec3s jointTable[STRAY_FAIRY_LIMB_MAX]; /* 0x188 */ Vec3s jointTable[STRAY_FAIRY_LIMB_MAX];
/* 0x1C4 */ ColliderCylinder collider; /* 0x1C4 */ ColliderCylinder collider;
/* 0x210 */ Actor* enemy; /* 0x210 */ Actor* enemy;
/* 0x214 */ u16 flags; /* 0x214 */ u16 strayFairyFlags;
/* 0x216 */ s16 direction; // negative when facing right, positive when facing left /* 0x216 */ s16 direction; // negative when facing right, positive when facing left
/* 0x218 */ s16 area; /* 0x218 */ s16 area;
/* 0x21C */ s32 timer; /* 0x21C */ s32 timer;