mirror of
https://github.com/zeldaret/tmc
synced 2026-06-05 11:18:43 -04:00
282 lines
7.4 KiB
C
282 lines
7.4 KiB
C
/**
|
|
* @file flyingSkull.c
|
|
* @ingroup Enemies
|
|
*
|
|
* @brief Flying Skull enemy
|
|
*/
|
|
#include "collision.h"
|
|
#include "enemy.h"
|
|
#include "entity.h"
|
|
#include "functions.h"
|
|
#include "hitbox.h"
|
|
|
|
typedef struct {
|
|
Entity base;
|
|
u8 filler[0xc];
|
|
u16 unk_0x74;
|
|
u8 unk_0x76;
|
|
} FlyingSkullEntity;
|
|
|
|
void (*const FlyingSkull_Functions[])(Entity*);
|
|
void (*const gUnk_080CFB9C[])(FlyingSkullEntity*);
|
|
void (*const gUnk_080CFBBC[])(FlyingSkullEntity*);
|
|
void (*const gUnk_080CFBD4[])(FlyingSkullEntity*);
|
|
const s8 gUnk_080CFBE4[4];
|
|
|
|
extern s32 sub_080012DC(Entity*);
|
|
extern void RegisterCarryEntity(Entity*);
|
|
|
|
void sub_0803A100(FlyingSkullEntity* this);
|
|
void sub_0803A0E0(FlyingSkullEntity* this);
|
|
|
|
void FlyingSkull(Entity* this) {
|
|
u32 index = sub_080012DC(this);
|
|
if (index) {
|
|
gUnk_080012C8[index](this);
|
|
} else {
|
|
FlyingSkull_Functions[GetNextFunction(this)](this);
|
|
}
|
|
}
|
|
|
|
void FlyingSkull_OnTick(FlyingSkullEntity* this) {
|
|
gUnk_080CFB9C[super->action](this);
|
|
}
|
|
|
|
void FlyingSkull_OnCollision(FlyingSkullEntity* this) {
|
|
sub_0803A100(this);
|
|
|
|
if (super->contactFlags == (CONTACT_TAKE_DAMAGE | 0x1d)) {
|
|
super->action = 7;
|
|
COLLISION_OFF(super);
|
|
super->zVelocity = Q_16_16(2.625);
|
|
super->spritePriority.b1 = 1;
|
|
SetBottomTile(this->unk_0x74, COORD_TO_TILE(super), super->collisionLayer);
|
|
} else if (super->z.HALF.HI) {
|
|
sub_0803A0E0(this);
|
|
}
|
|
|
|
EnemyFunctionHandlerAfterCollision(super, FlyingSkull_Functions);
|
|
}
|
|
|
|
void FlyingSkull_OnGrabbed(FlyingSkullEntity* this) {
|
|
gUnk_080CFBBC[super->subAction](this);
|
|
}
|
|
|
|
void sub_08039C98(FlyingSkullEntity* this) {
|
|
sub_0803A100(this);
|
|
super->subAction = 1;
|
|
super->timer = 0;
|
|
super->gustJarTolerance = 0x30;
|
|
}
|
|
|
|
void sub_08039CB0(FlyingSkullEntity* this) {
|
|
u32 offset;
|
|
sub_0803A100(this);
|
|
offset = sub_0806F520(super);
|
|
if (offset) {
|
|
sub_0806F4E8(super);
|
|
} else {
|
|
super->spriteOffsetX = offset;
|
|
if (super->z.HALF.HI) {
|
|
sub_0803A0E0(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_08039CE0(FlyingSkullEntity* this) {
|
|
if (super->timer == 0) {
|
|
sub_0803A100(this);
|
|
super->timer = 1;
|
|
super->z.HALF.HI = -1;
|
|
super->spriteOffsetX = 0;
|
|
SetBottomTile(this->unk_0x74, COORD_TO_TILE(super), super->collisionLayer);
|
|
}
|
|
|
|
if (sub_0806F520(super)) {
|
|
sub_0806F3E4(super);
|
|
} else {
|
|
sub_0803A0E0(this);
|
|
}
|
|
}
|
|
|
|
void sub_08039D4C(FlyingSkullEntity* this) {
|
|
if ((gPlayerState.field_0x1c & 0xf) == 0) {
|
|
sub_0803A0E0(this);
|
|
}
|
|
}
|
|
|
|
void nullsub_166(FlyingSkullEntity* this) {
|
|
}
|
|
|
|
void sub_08039D6C(FlyingSkullEntity* this) {
|
|
sub_0803A0E0(this);
|
|
}
|
|
|
|
void sub_08039D74(FlyingSkullEntity* this) {
|
|
u32 tmp;
|
|
super->action = 1;
|
|
super->gustJarFlags = 2;
|
|
super->carryFlags = 0;
|
|
super->y.HALF.HI += 3;
|
|
|
|
tmp = COORD_TO_TILE(super);
|
|
this->unk_0x74 = GetTileIndex(tmp, super->collisionLayer);
|
|
SetBottomTile(0x4060, tmp, super->collisionLayer);
|
|
InitializeAnimation(super, 0);
|
|
}
|
|
|
|
void sub_08039DD8(FlyingSkullEntity* this) {
|
|
sub_0803A100(this);
|
|
|
|
if (super->type == 0) {
|
|
if (GetTileTypeByEntity(super) == 0x4073) {
|
|
SetBottomTile(this->unk_0x74, COORD_TO_TILE(super), super->collisionLayer);
|
|
sub_0803A0E0(this);
|
|
}
|
|
|
|
RegisterCarryEntity(super);
|
|
} else {
|
|
if ((gPlayerState.flags & PL_MINISH) == 0) {
|
|
Entity* player = &gPlayerEntity.base;
|
|
if (EntityWithinDistance(super, player->x.HALF.HI, player->y.HALF.HI, 0x30)) {
|
|
if (super->type == 1) {
|
|
super->action = 3;
|
|
super->timer = 30;
|
|
} else {
|
|
player = CreateEnemy(STALFOS, super->type - 2);
|
|
if (player != NULL) {
|
|
player->type2 = 1;
|
|
CopyPosition(super, player);
|
|
SetBottomTile(this->unk_0x74, COORD_TO_TILE(super), super->collisionLayer);
|
|
DeleteEntity(super);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_08039ECC(FlyingSkullEntity* this) {
|
|
gUnk_080CFBD4[super->subAction](this);
|
|
}
|
|
|
|
void sub_08039EE4(FlyingSkullEntity* this) {
|
|
super->subAction = 1;
|
|
COLLISION_OFF(super);
|
|
super->collisions = COL_NONE;
|
|
super->hitbox = (Hitbox*)&gUnk_080FD340;
|
|
gPlayerEntity.base.animationState;
|
|
this->unk_0x76 = gPlayerEntity.base.animationState;
|
|
SetBottomTile(this->unk_0x74, COORD_TO_TILE(super), super->collisionLayer);
|
|
}
|
|
|
|
void sub_08039F4C(FlyingSkullEntity* this) {
|
|
if (gPlayerEntity.base.animationState != this->unk_0x76) {
|
|
super->frameIndex = AnimationStateIdle(gPlayerEntity.base.animationState - this->unk_0x76 + super->frameIndex);
|
|
this->unk_0x76 = gPlayerEntity.base.animationState;
|
|
}
|
|
}
|
|
|
|
void sub_08039F78(FlyingSkullEntity* this) {
|
|
super->spritePriority.b1 = 1;
|
|
if (super->z.HALF.HI == 0 || (super->collisions != COL_NONE)) {
|
|
sub_0803A0E0(this);
|
|
}
|
|
}
|
|
|
|
void sub_08039FA4(FlyingSkullEntity* this) {
|
|
sub_0803A0E0(this);
|
|
}
|
|
|
|
void sub_08039FAC(FlyingSkullEntity* this) {
|
|
sub_0803A100(this);
|
|
super->spriteOffsetX += gUnk_080CFBE4[super->timer & 3];
|
|
|
|
if (--super->timer == 0) {
|
|
super->action = 4;
|
|
COLLISION_ON(super);
|
|
super->spritePriority.b1 = 1;
|
|
super->spriteOffsetX = 0;
|
|
super->hitType = 0xa0;
|
|
super->flags2 = 0xf;
|
|
super->hitbox = (Hitbox*)&gUnk_080FD34C;
|
|
SetBottomTile(this->unk_0x74, COORD_TO_TILE(super), super->collisionLayer);
|
|
}
|
|
}
|
|
|
|
void sub_0803A048(FlyingSkullEntity* this) {
|
|
GetNextFrame(super);
|
|
super->z.WORD -= Q_16_16(1.0);
|
|
if (super->z.HALF.HI <= -6) {
|
|
super->action = 5;
|
|
super->timer = 10;
|
|
super->direction = GetFacingDirection(super, &gPlayerEntity.base);
|
|
}
|
|
}
|
|
|
|
void sub_0803A080(FlyingSkullEntity* this) {
|
|
GetNextFrame(super);
|
|
|
|
if (--super->timer == 0) {
|
|
super->action = 6;
|
|
}
|
|
}
|
|
|
|
void sub_0803A09C(FlyingSkullEntity* this) {
|
|
GetNextFrame(super);
|
|
ProcessMovement2(super);
|
|
|
|
if (super->collisions != COL_NONE) {
|
|
sub_0803A0E0(this);
|
|
}
|
|
}
|
|
|
|
void sub_0803A0B8(FlyingSkullEntity* this) {
|
|
if (super->zVelocity < 0) {
|
|
super->spriteSettings.flipY = 1;
|
|
}
|
|
|
|
if (GravityUpdate(super, Q_8_8(32.0)) == 0) {
|
|
sub_0803A0E0(this);
|
|
}
|
|
}
|
|
|
|
void sub_0803A0E0(FlyingSkullEntity* this) {
|
|
CreateFx(super, FX_BONE, sub_0808288C(super, super->type2, 0, 0));
|
|
DeleteThisEntity();
|
|
}
|
|
|
|
void sub_0803A100(FlyingSkullEntity* this) {
|
|
u32 tile = COORD_TO_TILE(super);
|
|
if (GetTileIndex(tile, super->collisionLayer) == 0x4067) {
|
|
SetBottomTile(this->unk_0x74, tile, super->collisionLayer);
|
|
DeleteThisEntity();
|
|
}
|
|
}
|
|
|
|
void (*const FlyingSkull_Functions[])(Entity*) = {
|
|
(EntityActionPtr)FlyingSkull_OnTick,
|
|
(EntityActionPtr)FlyingSkull_OnCollision,
|
|
GenericKnockback,
|
|
GenericDeath,
|
|
GenericConfused,
|
|
(EntityActionPtr)FlyingSkull_OnGrabbed,
|
|
};
|
|
|
|
void (*const gUnk_080CFB9C[])(FlyingSkullEntity*) = {
|
|
sub_08039D74, sub_08039DD8, sub_08039ECC, sub_08039FAC, sub_0803A048, sub_0803A080, sub_0803A09C, sub_0803A0B8,
|
|
};
|
|
|
|
void (*const gUnk_080CFBBC[])(FlyingSkullEntity*) = {
|
|
sub_08039C98, sub_08039CB0, sub_08039CE0, sub_08039D4C, nullsub_166, sub_08039D6C,
|
|
};
|
|
|
|
void (*const gUnk_080CFBD4[])(FlyingSkullEntity*) = {
|
|
sub_08039EE4,
|
|
sub_08039F4C,
|
|
sub_08039F78,
|
|
sub_08039FA4,
|
|
};
|
|
|
|
const s8 gUnk_080CFBE4[4] = { -1, 1, 1, -1 };
|