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="gStrayFairyGreatBayTexAnim" Offset="0x2C980" />
<TextureAnimation Name="gStrayFairyStoneTowerTexAnim" Offset="0x2C9F8" />
<Limb Name="gStrayFairyRightFacingHeadLimb" Type="Standard" Offset="0x2CA08" />
<Limb Name="gStrayFairyLeftWingLimb" Type="Standard" Offset="0x2CA14" />
<Limb Name="gStrayFairyRightWingLimb" Type="Standard" Offset="0x2CA20" />
<Limb Name="gStrayFairyGlowLimb" Type="Standard" Offset="0x2CA2C" />
<Limb Name="gStrayFairyTorsoLimb" Type="Standard" Offset="0x2CA38" />
<Limb Name="gStrayFairyRightArmLimb" Type="Standard" Offset="0x2CA44" />
<Limb Name="gStrayFairyPelvisAndLegsLimb" Type="Standard" Offset="0x2CA50" />
<Limb Name="gStrayFairyLeftArmLimb" Type="Standard" Offset="0x2CA5C" />
<Limb Name="gStrayFairyLeftFacingHeadLimb" Type="Standard" Offset="0x2CA68" />
<Skeleton Name="gStrayFairySkel" Type="Flex" LimbType="Standard" Offset="0x2CA98" />
<Limb Name="gStrayFairyRightFacingHeadLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_RIGHT_FACING_HEAD" Offset="0x2CA08" />
<Limb Name="gStrayFairyLeftWingLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_LEFT_WING" Offset="0x2CA14" />
<Limb Name="gStrayFairyRightWingLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_RIGHT_WING" Offset="0x2CA20" />
<Limb Name="gStrayFairyGlowLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_GLOW" Offset="0x2CA2C" />
<Limb Name="gStrayFairyTorsoLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_TORSO" Offset="0x2CA38" />
<Limb Name="gStrayFairyRightArmLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_RIGHT_ARM" Offset="0x2CA44" />
<Limb Name="gStrayFairyPelvisAndLegsLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_PELVIS_AND_LEGS" Offset="0x2CA50" />
<Limb Name="gStrayFairyLeftArmLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_LEFT_ARM" Offset="0x2CA5C" />
<Limb Name="gStrayFairyLeftFacingHeadLimb" Type="Standard" EnumName="STRAY_FAIRY_LIMB_LEFT_FACING_HEAD" Offset="0x2CA68" />
<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_02CB30" OutName="tex_02CB30" Format="i8" Width="16" Height="16" Offset="0x2CB30" />

View File

@ -1,6 +1,7 @@
#include "global.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_gi_hearts/object_gi_hearts.h"
#include "overlays/actors/ovl_En_Elforg/z_en_elforg.h"
#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);
}
} else {
spawnedActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELFORG, spawnPos->x, spawnPos->y + 40.0f,
spawnPos->z, 0, 0, 0, ((((param7F00 >> 8) & 0x7F) & 0x7F) << 9) | 7);
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));
if (param20000 == 0) {
if (!Flags_GetCollectible(play, (param7F00 >> 8) & 0x7F)) {
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,
spawnPos->z, 0, 0, 0, ((((param7F00 >> 8) & 0x7F) << 9) & 0xFE00) | 0x102);
} else {
spawnedActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELFORG, spawnPos->x, spawnPos->y + 40.0f,
spawnPos->z, 0, 0, 0, ((((param7F00 >> 8) & 0x7F) & 0x7F) << 9) | 7);
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));
}
if (Flags_GetCollectible(play, (param7F00 >> 8) & 0x7F) == 0) {
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,
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,
((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) {
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);
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,
((ENELFBUB_GET_SWITCHFLAG(&this->actor) & 0x7F) << 9) | 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), 0, STRAY_FAIRY_TYPE_BUBBLE));
if (childActor != NULL) {
childActor->parent = &this->actor;
}

View File

@ -241,7 +241,7 @@ void func_80A39DC8(EnElfgrp* this, PlayState* play, s32 arg2, s32 arg3) {
s32 pad;
s32 i;
Actor* elforg;
s32 temp;
s32 params;
Vec3f sp6C;
Player* player = GET_PLAYER(play);
@ -252,16 +252,16 @@ void func_80A39DC8(EnElfgrp* this, PlayState* play, s32 arg2, s32 arg3) {
if (arg3 == 0) {
sp6C = this->actor.world.pos;
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 {
sp6C = player->actor.world.pos;
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++) {
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) {
continue;
}
@ -284,8 +284,8 @@ s32 func_80A39F50(PlayState* play) {
}
elfOrg = (EnElforg*)itemAction;
if (!(elfOrg->flags & STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME)) {
elfOrg->flags |= STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME;
if (!(elfOrg->strayFairyFlags & STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME)) {
elfOrg->strayFairyFlags |= STRAY_FAIRY_FLAG_MOVES_QUICKLY_TO_HOME;
}
itemAction = itemAction->next;
}
@ -307,8 +307,8 @@ s32 func_80A39FBC(PlayState* play) {
}
elfOrg = (EnElforg*)itemAction;
if (!(elfOrg->flags & STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN)) {
elfOrg->flags |= STRAY_FAIRY_FLAG_CIRCLES_QUICKLY_IN_FOUNTAIN;
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;
}
@ -336,7 +336,7 @@ void func_80A3A044(PlayState* play) {
elfOrg = (EnElforg*)itemAction;
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;
}

View File

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

View File

@ -2,10 +2,12 @@
#define Z_EN_ELFORG_H
#include "global.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_FLAG_MOVES_QUICKLY_TO_HOME (1 << 0)
#define STRAY_FAIRY_FLAG_SPARKLES_AND_SHRINKS (1 << 1)
@ -13,40 +15,26 @@
#define STRAY_FAIRY_FLAG_GREAT_FAIRYS_MASK_EQUIPPED (1 << 3)
typedef enum {
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
STRAY_FAIRY_TYPE_BUBBLE, // The ones trapped in bubbles
STRAY_FAIRY_TYPE_CLOCK_TOWN, // The free-floating Stray Fairies in Clock Town
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
STRAY_FAIRY_TYPE_CHEST, // The ones in treasure chests
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
/* 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
} StrayFairyType;
typedef enum {
STRAY_FAIRY_AREA_CLOCK_TOWN,
STRAY_FAIRY_AREA_WOODFALL,
STRAY_FAIRY_AREA_SNOWHEAD,
STRAY_FAIRY_AREA_GREAT_BAY,
STRAY_FAIRY_AREA_STONE_TOWER,
STRAY_FAIRY_AREA_MAX
/* 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,
/* 5 */ STRAY_FAIRY_AREA_MAX
} 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;
typedef void (*EnElforgActionFunc)(struct EnElforg*, PlayState*);
@ -57,7 +45,7 @@ typedef struct EnElforg {
/* 0x188 */ Vec3s jointTable[STRAY_FAIRY_LIMB_MAX];
/* 0x1C4 */ ColliderCylinder collider;
/* 0x210 */ Actor* enemy;
/* 0x214 */ u16 flags;
/* 0x214 */ u16 strayFairyFlags;
/* 0x216 */ s16 direction; // negative when facing right, positive when facing left
/* 0x218 */ s16 area;
/* 0x21C */ s32 timer;