ovl_En_Ruppecrow OK with documentation (#502)

* Implement EnRuppecrow_Init

* Implement EnRuppecrow_Destroy

* Implement EnRuppecrow_Update

* Implement EnRuppecrow_Draw

* Implement func_80BE2260, func_80BE2808

* Implement func_80BE30F4

* Implement func_80BE2F6C

* Implement func_80BE35A4

* Implement func_80BE2728

* Initial work on func_80BE2B80

* Implement func_80BE2B80

* Implement func_80BE2794

* Implement func_80BE3354

* Implement func_80BE348C

* Implement func_80BE2E18

* Implement func_80BE2D4C

* Run format script for cleanup

* Implement func_80BE2668

* Implement func_80BE3178

* Implement func_80BE32DC

* Initial work on func_80BE2874

* Implement func_80BE2874

* Implement func_80BE2330

* Implement func_80BE24CC

* Move static data into C file

* Rename D_WORDs to static names

* Format and document EnRuppecrow

* Update documentation

* Apply feedback

* Remove unecessary struct padding

* Implement review suggestions

* Run actorfixer

* Use object header
This commit is contained in:
Nick Sturgeon
2022-01-04 00:02:53 -05:00
committed by GitHub
parent de61e04312
commit 78cb55ce97
4 changed files with 602 additions and 54 deletions
+1 -2
View File
@@ -4919,8 +4919,7 @@ beginseg
name "ovl_En_Ruppecrow"
compress
include "build/src/overlays/actors/ovl_En_Ruppecrow/z_en_ruppecrow.o"
include "build/data/ovl_En_Ruppecrow/ovl_En_Ruppecrow.data.o"
include "build/data/ovl_En_Ruppecrow/ovl_En_Ruppecrow.reloc.o"
include "build/src/overlays/actors/ovl_En_Ruppecrow/ovl_En_Ruppecrow_reloc.o"
endseg
beginseg
@@ -5,17 +5,41 @@
*/
#include "z_en_ruppecrow.h"
#include "objects/object_crow/object_crow.h"
#define FLAGS 0x00004030
#define THIS ((EnRuppecrow*)thisx)
enum {
ENRUPPECROW_EFFECT_NONE = 0,
ENRUPPECROW_EFFECT_ICE = 10,
ENRUPPECROW_EFFECT_LIGHT = 20,
};
void EnRuppecrow_Init(Actor* thisx, GlobalContext* globalCtx);
void EnRuppecrow_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnRuppecrow_Update(Actor* thisx, GlobalContext* globalCtx);
void EnRuppecrow_Draw(Actor* thisx, GlobalContext* globalCtx);
void EnRuppecrow_HandleSong(EnRuppecrow*, GlobalContext*);
s32 EnRuppecrow_UpdateCollision(EnRuppecrow*, GlobalContext*);
void EnRuppecrow_UpdateRupees(EnRuppecrow*);
void EnRuppecrow_UpdateDamage(EnRuppecrow*, GlobalContext*);
void EnRuppecrow_HandleDeath(EnRuppecrow*);
void EnRuppecrow_FallToDespawn(EnRuppecrow*, GlobalContext*);
void EnRuppecrow_ShatterIce(EnRuppecrow*, GlobalContext*);
void EnRuppecrow_UpdatePosition(EnRuppecrow*, GlobalContext*);
s32 EnRuppecrow_CheckPlayedMatchingSong(GlobalContext*);
void EnRuppecrow_HandleSongCutscene(EnRuppecrow*, GlobalContext*);
s32 EnRuppecrow_ReachedPointClockwise(EnRuppecrow*, Path*, s32);
s32 EnRuppecrow_ReachedPointCounterClockwise(EnRuppecrow*, Path*, s32);
f32 EnRuppecrow_GetPointDirection(Path*, s32, PosRot*, Vec3s*);
s32 EnRuppecrow_CanSpawnBlueRupees(GlobalContext*);
void EnRuppecrow_SpawnRupee(EnRuppecrow*, GlobalContext*);
void EnRuppecrow_FlyWhileDroppingRupees(EnRuppecrow*, GlobalContext*);
void EnRuppecrow_UpdateSpeed(EnRuppecrow*, GlobalContext*);
void EnRuppecrow_FlyToDespawn(EnRuppecrow*, GlobalContext*);
#if 0
const ActorInit En_Ruppecrow_InitVars = {
ACTOR_EN_RUPPECROW,
ACTORCAT_ENEMY,
@@ -28,25 +52,36 @@ const ActorInit En_Ruppecrow_InitVars = {
(ActorFunc)EnRuppecrow_Draw,
};
// static ColliderJntSphElementInit sJntSphElementsInit[1] = {
static ColliderJntSphElementInit D_80BE39B0[1] = {
static ColliderJntSphElementInit sJntSphElementsInit[1] = {
{
{ ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
{
ELEMTYPE_UNK0,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ 1, { { 0, 0, 0 }, 20 }, 100 },
},
};
// static ColliderJntSphInit sJntSphInit = {
static ColliderJntSphInit D_80BE39D4 = {
{ COLTYPE_HIT3, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_JNTSPH, },
1, D_80BE39B0, // sJntSphElementsInit,
static ColliderJntSphInit sJntSphInit = {
{
COLTYPE_HIT3,
AT_NONE,
AC_ON | AC_TYPE_PLAYER,
OC1_ON | OC1_TYPE_ALL,
OC2_TYPE_1,
COLSHAPE_JNTSPH,
},
1,
sJntSphElementsInit,
};
// sColChkInfoInit
static CollisionCheckInfoInit D_80BE39E4 = { 1, 15, 30, 30 };
static CollisionCheckInfoInit sColChkInfoInit = { 1, 15, 30, 30 };
// static DamageTable sDamageTable = {
static DamageTable D_80BE39EC = {
static DamageTable sDamageTable = {
/* Deku Nut */ DMG_ENTRY(0, 0x1),
/* Deku Stick */ DMG_ENTRY(1, 0x0),
/* Horse trample */ DMG_ENTRY(1, 0x0),
@@ -81,62 +116,558 @@ static DamageTable D_80BE39EC = {
/* Powder Keg */ DMG_ENTRY(1, 0x0),
};
// static InitChainEntry sInitChain[] = {
static InitChainEntry D_80BE3A0C[] = {
static InitChainEntry sInitChain[] = {
ICHAIN_F32_DIV1000(gravity, -500, ICHAIN_CONTINUE),
ICHAIN_F32(targetArrowOffset, 2000, ICHAIN_STOP),
};
#endif
s32 EnRuppecrow_UpdateCollision(EnRuppecrow* this, GlobalContext* globalCtx) {
s32 pad;
extern ColliderJntSphElementInit D_80BE39B0[1];
extern ColliderJntSphInit D_80BE39D4;
extern CollisionCheckInfoInit D_80BE39E4;
extern DamageTable D_80BE39EC;
extern InitChainEntry D_80BE3A0C[];
this->collider.elements->dim.worldSphere.center.x = this->actor.world.pos.x;
this->collider.elements->dim.worldSphere.center.y =
sJntSphInit.elements->dim.modelSphere.center.y + this->actor.world.pos.y;
this->collider.elements->dim.worldSphere.center.z = this->actor.world.pos.z;
extern UNK_TYPE D_060000F0;
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 12.0f, 25.0f, 50.0f, 0x07);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2260.s")
return true;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2330.s")
s32 EnRuppecrow_ReachedPointClockwise(EnRuppecrow* this, Path* path, s32 pointIndex) {
Vec3s* points = Lib_SegmentedToVirtual(path->points);
s32 pathCount = path->count;
s32 currentPoint = pointIndex;
s32 reached = false;
f32 diffX;
f32 diffZ;
f32 px;
f32 pz;
f32 d;
Vec3f point;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE24CC.s")
Math_Vec3s_ToVec3f(&point, &points[currentPoint]);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2668.s")
if (currentPoint == 0) {
diffX = points[1].x - points[0].x;
diffZ = points[1].z - points[0].z;
} else {
if (currentPoint == (pathCount - 1)) {
diffX = points[pathCount - 1].x - points[pathCount - 2].x;
diffZ = points[pathCount - 1].z - points[pathCount - 2].z;
} else {
diffX = points[currentPoint + 1].x - points[currentPoint - 1].x;
diffZ = points[currentPoint + 1].z - points[currentPoint - 1].z;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2728.s")
func_8017B7F8(&point, RADF_TO_BINANG(func_80086B30(diffX, diffZ)), &px, &pz, &d);
if (((this->actor.world.pos.x * px) + (pz * this->actor.world.pos.z) + d) > 0.0f) {
reached = true;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2794.s")
return reached;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2808.s")
s32 EnRuppecrow_ReachedPointCounterClockwise(EnRuppecrow* this, Path* path, s32 pointIndex) {
Vec3s* points = Lib_SegmentedToVirtual(path->points);
s32 pathCount = path->count;
s32 currentPoint = pointIndex;
s32 reached = false;
f32 diffX;
f32 diffZ;
f32 px;
f32 pz;
f32 d;
Vec3f point;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2874.s")
Math_Vec3s_ToVec3f(&point, &points[currentPoint]);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2B80.s")
if (currentPoint == 0) {
diffX = points[0].x - points[1].x;
diffZ = points[0].z - points[1].z;
} else {
if (currentPoint == (pathCount - 1)) {
diffX = points[pathCount - 2].x - points[pathCount - 1].x;
diffZ = points[pathCount - 2].z - points[pathCount - 1].z;
} else {
diffX = points[currentPoint - 1].x - points[currentPoint + 1].x;
diffZ = points[currentPoint - 1].z - points[currentPoint + 1].z;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2D4C.s")
func_8017B7F8(&point, RADF_TO_BINANG(func_80086B30(diffX, diffZ)), &px, &pz, &d);
if (((this->actor.world.pos.x * px) + (pz * this->actor.world.pos.z) + d) > 0.0f) {
reached = true;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2E18.s")
return reached;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2F6C.s")
f32 EnRuppecrow_GetPointDirection(Path* path, s32 pointIndex, PosRot* world, Vec3s* direction) {
Vec3s* points;
Vec3f point;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE30F4.s")
if (path != NULL) {
points = Lib_SegmentedToVirtual(path->points);
points = &points[pointIndex];
VEC_SET(point, points->x, points->y, points->z);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE3178.s")
direction->y = Math_Vec3f_Yaw(&world->pos, &point);
direction->x = Math_Vec3f_Pitch(&world->pos, &point);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE32DC.s")
return point.y - world->pos.y;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE3354.s")
void EnRuppecrow_ShatterIce(EnRuppecrow* this, GlobalContext* globalCtx) {
if (this->currentEffect == ENRUPPECROW_EFFECT_ICE) {
this->currentEffect = ENRUPPECROW_EFFECT_NONE;
this->unk_2C8 = 0.0f;
func_800BF7CC(globalCtx, &this->actor, this->limbPos, ENRUPPECROW_LIMB_POS_COUNT, 0x2, 0.2f, 0.2f);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE348C.s")
s32 EnRuppecrow_CanSpawnBlueRupees(GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE35A4.s")
switch (player->transformation) {
case PLAYER_FORM_DEKU:
return false;
case PLAYER_FORM_GORON:
return true;
case PLAYER_FORM_ZORA:
return false;
case PLAYER_FORM_HUMAN:
if (player->stateFlags1 & 0x800000) {
return true;
} else {
return false;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/EnRuppecrow_Init.s")
return false;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/EnRuppecrow_Destroy.s")
void EnRuppecrow_UpdateRupees(EnRuppecrow* this) {
EnItem00* rupee;
s16 rupeeIndex;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/EnRuppecrow_Update.s")
for (rupeeIndex = 0; rupeeIndex < ENRUPPECROW_RUPEE_COUNT; rupeeIndex++) {
rupee = this->rupees[rupeeIndex];
if (rupee != NULL && rupee->unk152 == 0) {
Actor_MarkForDeath(&rupee->actor);
}
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/EnRuppecrow_Draw.s")
void EnRuppecrow_SpawnRupee(EnRuppecrow* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
f32 xOffset;
EnItem00* rupee;
s16 rupeeIndex = this->rupeeIndex;
if (!(player->stateFlags3 & 0x1000)) {
xOffset = (this->rupeeIndex & 1) ? 10.0f : -10.0f;
} else {
xOffset = 0.0f;
}
if (EnRuppecrow_CanSpawnBlueRupees(globalCtx) && (this->rupeeIndex % 5) == 4) {
if (this->rupeeIndex == 19) {
rupee = (EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00,
this->actor.world.pos.x + xOffset, this->actor.world.pos.y,
this->actor.world.pos.z, 0x0, 0x0, 0x0, ITEM00_RUPEE_RED);
this->rupees[rupeeIndex] = rupee;
this->rupees[rupeeIndex]->actor.gravity = -5.0f;
this->rupees[rupeeIndex]->actor.velocity.y = 0.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_RUPY_FALL);
rupee = this->rupees[rupeeIndex];
rupee->unk152 = 60;
this->rupees[rupeeIndex]->actor.flags |= 0x10;
} else {
rupee = (EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00,
this->actor.world.pos.x + xOffset, this->actor.world.pos.y,
this->actor.world.pos.z, 0x0, 0x0, 0x0, ITEM00_RUPEE_BLUE);
this->rupees[rupeeIndex] = rupee;
this->rupees[rupeeIndex]->actor.gravity = -5.0f;
this->rupees[rupeeIndex]->actor.velocity.y = 0.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_RUPY_FALL);
rupee = this->rupees[rupeeIndex];
rupee->unk152 = 60;
this->rupees[rupeeIndex]->actor.flags |= 0x10;
}
} else if (this->rupeeIndex == 19) {
rupee =
(EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00, this->actor.world.pos.x + xOffset,
this->actor.world.pos.y, this->actor.world.pos.z, 0x0, 0x0, 0x0, ITEM00_RUPEE_RED);
this->rupees[rupeeIndex] = rupee;
this->rupees[rupeeIndex]->actor.gravity = -5.0f;
this->rupees[rupeeIndex]->actor.velocity.y = 0.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_RUPY_FALL);
rupee = this->rupees[rupeeIndex];
rupee->unk152 = 60;
this->rupees[rupeeIndex]->actor.flags |= 0x10;
} else {
rupee =
(EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00, this->actor.world.pos.x + xOffset,
this->actor.world.pos.y, this->actor.world.pos.z, 0x0, 0x0, 0x0, ITEM00_RUPEE_GREEN);
this->rupees[rupeeIndex] = rupee;
this->rupees[rupeeIndex]->actor.gravity = -5.0f;
this->rupees[rupeeIndex]->actor.velocity.y = 0.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_RUPY_FALL);
rupee = this->rupees[rupeeIndex];
rupee->unk152 = 60;
this->rupees[rupeeIndex]->actor.flags |= 0x10;
}
this->rupeeIndex++;
}
void EnRuppecrow_UpdatePosition(EnRuppecrow* this, GlobalContext* globalCtx) {
Vec3s nextPointDirection;
EnRuppecrow_GetPointDirection(this->path, this->currentPoint, &this->actor.world, &nextPointDirection);
if (this->actor.bgCheckFlags & 0x8) {
nextPointDirection.y = this->actor.wallYaw;
}
Math_SmoothStepToS(&this->actor.world.rot.y, nextPointDirection.y, 0x4, 0x3E8, 0x1);
this->actor.shape.rot.y = this->actor.world.rot.y;
Math_SmoothStepToS(&this->actor.world.rot.x, -nextPointDirection.x, 0x4, 0x3E8, 0x1);
if (this->isGoingCounterClockwise & 1) {
if (EnRuppecrow_ReachedPointCounterClockwise(this, this->path, this->currentPoint)) {
if (this->currentPoint <= 0) {
this->currentPoint = this->path->count - 1;
} else {
this->currentPoint--;
}
if (this->actionFunc == EnRuppecrow_FlyWhileDroppingRupees &&
(!EnRuppecrow_CanSpawnBlueRupees(globalCtx) || (this->currentPoint % -2) == 0)) {
EnRuppecrow_SpawnRupee(this, globalCtx);
}
}
} else if (EnRuppecrow_ReachedPointClockwise(this, this->path, this->currentPoint)) {
if (this->currentPoint >= this->path->count - 1) {
this->currentPoint = 0;
} else {
this->currentPoint++;
}
if (this->actionFunc == EnRuppecrow_FlyWhileDroppingRupees &&
(!EnRuppecrow_CanSpawnBlueRupees(globalCtx) || (this->currentPoint % -2) == 0)) {
EnRuppecrow_SpawnRupee(this, globalCtx);
}
}
}
s32 EnRuppecrow_CheckPlayedMatchingSong(GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
if (globalCtx->msgCtx.unk1202A == 0x3) {
switch (player->transformation) {
case PLAYER_FORM_DEKU:
if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_SONATA) {
return true;
}
break;
case PLAYER_FORM_GORON:
if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_GORON_LULLABY) {
return true;
}
break;
case PLAYER_FORM_ZORA:
if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_NEW_WAVE) {
return true;
}
break;
case PLAYER_FORM_HUMAN:
if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_SONATA) {
return true;
} else if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_GORON_LULLABY) {
return true;
} else if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_NEW_WAVE) {
return true;
}
break;
}
}
return false;
}
void EnRuppecrow_UpdateSpeed(EnRuppecrow* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
switch (player->transformation) {
case PLAYER_FORM_DEKU:
this->speedModifier = 7.0f;
break;
case PLAYER_FORM_GORON:
if (player->stateFlags3 & 0x1000) { // Goron Link is curled
this->speedModifier = 19.0f;
} else {
this->speedModifier = 7.0f;
}
break;
case PLAYER_FORM_ZORA:
this->speedModifier = 7.0f;
break;
case PLAYER_FORM_HUMAN:
if (player->stateFlags1 & 0x800000) {
this->speedModifier = 16.0f;
} else {
this->speedModifier = 7.0f;
}
break;
}
this->skelAnime.playSpeed = this->speedModifier / 6.0f;
if (this->actor.xzDistToPlayer > 800.0f) {
this->speedModifier *= 0.5f;
} else if (this->actor.xzDistToPlayer > 500.0f) {
this->speedModifier *= 0.8f;
} else if (this->actor.xzDistToPlayer < 150.0f) {
this->speedModifier *= 1.2f;
}
}
void EnRuppecrow_HandleDeath(EnRuppecrow* this) {
f32 scale;
this->actor.speedXZ *= Math_CosS(this->actor.world.rot.x);
this->actor.velocity.y = 0.0f;
Animation_Change(&this->skelAnime, &object_crow_Anim_0000F0, 0.4f, 0.0f, 0.0f, 0x1, -3.0f);
this->actor.shape.yOffset = 0.0f;
this->actor.targetArrowOffset = 0.0f;
this->actor.bgCheckFlags &= ~0x1;
scale = this->actor.scale.x * 100.0f;
this->actor.world.pos.y += 20.0f * scale;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_DEAD);
this->unk_2CC = 0.5f;
if (this->actor.colChkInfo.damageEffect == 0x3) {
this->currentEffect = ENRUPPECROW_EFFECT_ICE;
this->unk_2C8 = 1.0f;
this->iceSfxTimer = 0.75f;
} else if (this->actor.colChkInfo.damageEffect == 0x4) {
this->currentEffect = ENRUPPECROW_EFFECT_LIGHT;
this->unk_2C8 = 5.0f;
} else if (this->actor.colChkInfo.damageEffect == 0x2) {
this->currentEffect = ENRUPPECROW_EFFECT_NONE;
this->unk_2C8 = 5.0f;
}
func_800BCB70(&this->actor, 0x4000, 0xFF, 0x0, 0x28);
if (this->actor.flags & 0x8000) {
this->actor.speedXZ = 0.0f;
}
this->collider.base.acFlags &= ~AC_ON;
this->actor.flags |= 0x10;
this->actionFunc = EnRuppecrow_FallToDespawn;
}
void EnRuppecrow_UpdateDamage(EnRuppecrow* this, GlobalContext* globalCtx) {
if (this->collider.base.acFlags & AC_HIT) {
this->collider.base.acFlags &= ~AC_HIT;
func_800BE258(&this->actor, this->collider.elements);
if (this->actor.colChkInfo.damageEffect != 0x1) {
this->actor.colChkInfo.health = 0;
this->actor.flags &= ~0x1;
Enemy_StartFinishingBlow(globalCtx, &this->actor);
EnRuppecrow_HandleDeath(this);
}
}
}
void EnRuppecrow_HandleSong(EnRuppecrow* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
EnRuppecrow_UpdatePosition(this, globalCtx);
if (this->actor.xzDistToPlayer < 1000.0f && EnRuppecrow_CheckPlayedMatchingSong(globalCtx)) {
// If Link is in front, the guay will turn around and go the other way
if (Actor_IsActorFacingLink(&this->actor, 0x4000)) {
this->isGoingCounterClockwise |= 1;
if (this->currentPoint > 0) {
this->currentPoint--;
} else {
this->currentPoint = this->path->count - 1;
}
}
ActorCutscene_SetIntentToPlay(this->actor.cutscene);
this->actionFunc = EnRuppecrow_HandleSongCutscene;
}
if (player->stateFlags2 & 0x8000000) {
Math_ApproachF(&this->actor.speedXZ, 0.0f, 0.1f, 1.0f);
} else {
Math_ApproachF(&this->actor.speedXZ, 6.0f, 0.1f, 0.1f);
}
Actor_SetVelocityAndMoveXYRotation(&this->actor);
this->yOffset += 0x1000;
this->actor.shape.yOffset = Math_SinS(this->yOffset) * 500.0f;
if ((globalCtx->state.frames % 43) == 0) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_CRY);
}
}
void EnRuppecrow_HandleSongCutscene(EnRuppecrow* this, GlobalContext* globalCtx) {
EnRuppecrow_UpdatePosition(this, globalCtx);
if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) {
ActorCutscene_Start(this->actor.cutscene, &this->actor);
EnRuppecrow_UpdateSpeed(this, globalCtx);
this->actionFunc = EnRuppecrow_FlyWhileDroppingRupees;
} else {
ActorCutscene_SetIntentToPlay(this->actor.cutscene);
}
Actor_SetVelocityAndMoveXYRotation(&this->actor);
}
void EnRuppecrow_FlyWhileDroppingRupees(EnRuppecrow* this, GlobalContext* globalCtx) {
EnRuppecrow_UpdatePosition(this, globalCtx);
if (this->rupeeIndex >= ENRUPPECROW_RUPEE_COUNT) {
// Finished spawning rupees; fly up and then despawn
this->speedModifier = 6.0f;
// Source of the "Termina Field Guay Glitch"; guay will no longer fall if killed after this point
this->actor.gravity = 0.0f;
Math_ApproachF(&this->actor.speedXZ, 6.0f, 0.2f, 0.5f);
Math_ApproachF(&this->actor.velocity.y, 3.0f, 0.2f, 0.5f);
this->actionFunc = EnRuppecrow_FlyToDespawn;
this->skelAnime.playSpeed = 1.0f;
Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor);
} else {
if (ActorCutscene_GetCurrentIndex() != this->actor.cutscene) {
EnRuppecrow_UpdateSpeed(this, globalCtx);
Math_ApproachF(&this->actor.speedXZ, this->speedModifier, 0.2f, 0.5f);
}
Actor_SetVelocityAndMoveXYRotation(&this->actor);
this->yOffset += 0x1000;
this->actor.shape.yOffset = Math_SinS(this->yOffset) * 500.0f;
if ((globalCtx->state.frames % 43) == 0) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_CRY);
}
}
}
void EnRuppecrow_FlyToDespawn(EnRuppecrow* this, GlobalContext* globalCtx) {
if (this->actor.bgCheckFlags & 0x8) {
this->actor.world.rot.y *= -0x1;
}
Math_ApproachF(&this->actor.speedXZ, this->speedModifier, 0.1f, 0.1f);
Math_ApproachF(&this->actor.velocity.y, 3.0f, 0.2f, 0.5f);
if (this->actor.world.pos.y > 1000.0f || this->actor.xzDistToPlayer > 2000.0f) {
Actor_MarkForDeath(&this->actor);
} else {
this->yOffset += 0x800;
this->actor.shape.yOffset = Math_SinS(this->yOffset) * 500.0f;
Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor);
if ((globalCtx->state.frames % 43) == 0) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_CRY);
}
}
}
void EnRuppecrow_FallToDespawn(EnRuppecrow* this, GlobalContext* globalCtx) {
Math_StepToF(&this->actor.speedXZ, 0.0f, 0.5f);
if (this->currentEffect != ENRUPPECROW_EFFECT_ICE) {
Math_StepToF(&this->unk_2C8, 0.0f, 0.05f);
this->unk_2CC = (this->unk_2C8 + 1.0f) * 0.25f;
this->unk_2CC = CLAMP_MAX(this->unk_2CC, 0.5f);
} else if (!Math_StepToF(&this->iceSfxTimer, 0.5f, 0.0125f)) {
func_800B9010(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG);
}
this->actor.colorFilterTimer = 40;
if (!(this->actor.flags & 0x8000)) {
if (this->currentEffect != ENRUPPECROW_EFFECT_ICE) {
Math_ScaledStepToS(&this->actor.shape.rot.x, 0x4000, 0x200);
this->actor.shape.rot.z += 0x1780;
}
if (this->actor.bgCheckFlags & 0x1 || this->actor.floorHeight == BGCHECK_Y_MIN) {
EnRuppecrow_ShatterIce(this, globalCtx);
func_800B3030(globalCtx, &this->actor.world.pos, &gZeroVec3f, &gZeroVec3f, (this->actor.scale.x * 10000.0f),
0x0, 0x0);
Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 0xB, NA_SE_EN_EXTINCT);
Actor_MarkForDeath(&this->actor);
return;
}
}
Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor);
}
void EnRuppecrow_Init(Actor* thisx, GlobalContext* globalCtx2) {
EnRuppecrow* this = THIS;
GlobalContext* globalCtx = globalCtx2;
Actor_ProcessInitChain(&this->actor, sInitChain);
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_crow_Skel_0010C0, &object_crow_Anim_0000F0, this->joinTable,
this->morphTable, ENRUPPECROW_LIMB_COUNT);
ActorShape_Init(&this->actor.shape, 2000.0f, func_800B3FC0, 20.0f);
Collider_InitJntSph(globalCtx, &this->collider);
Collider_InitAndSetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, &this->colliderElement);
this->collider.elements->dim.worldSphere.radius = sJntSphInit.elements->dim.modelSphere.radius;
CollisionCheck_SetInfo(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit);
Actor_SetScale(&this->actor, 0.01f);
this->actor.flags |= 0x2000000;
this->path = func_8013D648(globalCtx, ENRUPPECROW_GET_PATH(&this->actor), 0x3F);
if (this->path != NULL) {
this->actionFunc = EnRuppecrow_HandleSong;
} else {
Actor_MarkForDeath(&this->actor);
}
}
void EnRuppecrow_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnRuppecrow* this = THIS;
Collider_DestroyJntSph(globalCtx, &this->collider);
}
void EnRuppecrow_Update(Actor* thisx, GlobalContext* globalCtx) {
EnRuppecrow* this = THIS;
EnRuppecrow_UpdateDamage(this, globalCtx);
this->actionFunc(this, globalCtx);
EnRuppecrow_UpdateRupees(this);
this->actor.focus.pos = this->actor.world.pos;
SkelAnime_Update(&this->skelAnime);
EnRuppecrow_UpdateCollision(this, globalCtx);
}
void EnRuppecrow_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnRuppecrow* this = THIS;
func_8012C28C(globalCtx->state.gfxCtx);
SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
NULL, NULL, &this->actor);
}
@@ -3,15 +3,38 @@
#include "global.h"
#define ENRUPPECROW_GET_PATH(thisx) (((thisx)->params & 0xFC00) >> 0xA)
#define ENRUPPECROW_RUPEE_COUNT 20
#define ENRUPPECROW_LIMB_COUNT 9
#define ENRUPPECROW_LIMB_POS_COUNT 4
struct EnRuppecrow;
typedef void (*EnRuppecrowActionFunc)(struct EnRuppecrow*, GlobalContext*);
typedef struct EnRuppecrow {
/* 0x0000 */ Actor actor;
/* 0x0144 */ char unk_144[0x94];
/* 0x01D8 */ EnRuppecrowActionFunc actionFunc;
/* 0x01DC */ char unk_1DC[0x128];
/* 0x000 */ Actor actor;
/* 0x144 */ EnItem00* rupees[ENRUPPECROW_RUPEE_COUNT];
/* 0x194 */ SkelAnime skelAnime;
/* 0x1D8 */ EnRuppecrowActionFunc actionFunc;
/* 0x1DC */ UNK_TYPE4 unk_1DC; // unused
/* 0x1E0 */ Vec3s joinTable[ENRUPPECROW_LIMB_COUNT];
/* 0x216 */ Vec3s morphTable[ENRUPPECROW_LIMB_COUNT];
/* 0x24C */ Path* path;
/* 0x250 */ s32 currentPoint;
/* 0x254 */ ColliderJntSph collider;
/* 0x274 */ ColliderJntSphElement colliderElement;
/* 0x2B4 */ u16 isGoingCounterClockwise;
/* 0x2B8 */ f32 speedModifier;
/* 0x2BC */ s16 rupeeIndex;
/* 0x2BE */ s16 yOffset;
/* 0x2C0 */ UNK_TYPE4 unk_2C0; // unused
/* 0x2C4 */ u8 currentEffect;
/* 0x2C8 */ f32 unk_2C8; // set but not used
/* 0x2CC */ f32 unk_2CC; // set but not used
/* 0x2D0 */ f32 iceSfxTimer;
/* 0x2D4 */ Vec3f limbPos[ENRUPPECROW_LIMB_POS_COUNT];
} EnRuppecrow; // size = 0x304
extern const ActorInit En_Ruppecrow_InitVars;
-5
View File
@@ -3311,11 +3311,6 @@ D_06009220 = 0x06009220;
D_0600C700 = 0x0600C700;
// ovl_En_Ruppecrow
D_060000F0 = 0x060000F0;
D_060010C0 = 0x060010C0;
// ovl_En_Rz
D_06003A20 = 0x06003A20;