summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/enemy/enemy64.c523
1 files changed, 523 insertions, 0 deletions
diff --git a/src/enemy/enemy64.c b/src/enemy/enemy64.c
new file mode 100644
index 00000000..8fde9fbc
--- /dev/null
+++ b/src/enemy/enemy64.c
@@ -0,0 +1,523 @@
+/**
+ * @file enemy64.c
+ * @ingroup Enemies
+ *
+ * @brief Enemy64 enemy
+ */
+
+#define NENT_DEPRECATED
+#include "global.h"
+#include "enemy.h"
+#include "functions.h"
+#include "fade.h"
+
+typedef struct {
+ /*0x00*/ Entity base;
+ /*0x68*/ u8 unk_68[0x6];
+ /*0x6e*/ u8 unk_6e;
+ /*0x6f*/ u8 unk_6f[0x5];
+ /*0x74*/ s16 unk_74;
+ /*0x76*/ u16 unk_76;
+ /*0x78*/ u16 unk_78;
+ /*0x7a*/ u16 unk_7a;
+ /*0x7c*/ u8 unk_7c;
+ /*0x7d*/ u8 unk_7d;
+ /*0x7e*/ u16 unk_7e;
+ /*0x80*/ u16 unk_80;
+ /*0x82*/ u16 unk_82;
+} Enemy64Entity;
+
+extern void sub_08047EA4(Entity*, u32); // gyorgMale
+
+extern void (*const Enemy64_Actions[])(Enemy64Entity*);
+extern void (*const Enemy64_Action1_SubActions[])(Enemy64Entity*);
+extern void (*const Enemy64_Action2_SubActions[])(Enemy64Entity*);
+extern void (*const Enemy64_Action3_SubActions[])(Enemy64Entity*);
+extern const u8 gUnk_080D29B8[];
+extern void (*const Enemy64_Action4_SubActions[])(Enemy64Entity*);
+
+void sub_080499F0(Enemy64Entity*);
+void sub_08049998(Enemy64Entity*, u32);
+void Enemy64_Action2_SubAction1(Enemy64Entity*);
+void sub_08049944(Enemy64Entity*);
+bool32 sub_08049A8C(Enemy64Entity*);
+void sub_08049AB0(Enemy64Entity*);
+void sub_08049B20(Enemy64Entity*);
+
+void Enemy64(Enemy64Entity* this) {
+ if (super->action != 0) {
+ super->spriteSettings.draw = this->unk_7d;
+ }
+ if (super->health == 0) {
+ super->health = 0xff;
+ super->action = 4;
+ super->subAction = 0;
+ }
+ Enemy64_Actions[super->action](this);
+ sub_0805EC9C(super, 0xaa, 0xaa, this->unk_78);
+ super->animationState = -(this->unk_78 >> 8);
+ sub_080499F0(this);
+ this->unk_7d = super->spriteSettings.draw;
+ if (((super->spriteSettings.draw == 1) && (0x100 < (super->y.HALF.HI - gRoomControls.scroll_y) + 0x30U))) {
+ super->spriteSettings.draw = 0;
+ }
+}
+
+void Enemy64_Init(Enemy64Entity* this) {
+ Entity* tail;
+
+ if (CheckFlags(0x7c)) {
+ SetTile(0x4081, 10, 2);
+ SetTile(0x4081, 0x4a, 2);
+ SetTile(0x4081, 0x8a, 2);
+ SetTile(0x4081, 0xca, 2);
+ DeleteThisEntity();
+ } else {
+ sub_0807B7D8(0x323, 10, 1);
+ sub_0807B7D8(0x323, 0x4a, 1);
+ sub_0807B7D8(0x323, 0x8a, 1);
+ sub_0807B7D8(0x323, 0xca, 1);
+ }
+ tail = CreateProjectile(GYORG_TAIL);
+ if (tail != NULL) {
+ tail->type = 1;
+ tail->parent = super;
+ super->child = tail;
+ super->action = 1;
+ super->subAction = 0;
+ super->actionDelay = 0x3c;
+ super->direction = 0xc0;
+ super->animationState = 0xc0;
+ super->speed = 0x300;
+ super->spriteRendering.b0 = 3;
+ super->spriteSettings.draw = 1;
+ super->spriteOrientation.flipY = 2;
+ super->spriteRendering.b3 = 2;
+ super->collisionLayer = 2;
+ this->unk_7c = 0;
+ this->unk_78 = 0x4000;
+ this->unk_7a = 0x4000;
+ InitAnimationForceUpdate(super, 0);
+ }
+}
+
+void Enemy64_Action1(Enemy64Entity* this) {
+ Enemy64_Action1_SubActions[super->subAction](this);
+ UpdateAnimationSingleFrame(super);
+}
+
+void Enemy64_Action1_SubAction0(Enemy64Entity* this) {
+ if (super->actionDelay != 0) {
+ super->actionDelay--;
+ } else {
+ sub_08049998(this, ((0x100 - super->direction) & 0xff) << 8);
+ if ((gRoomControls.origin_x - 0x100) > super->x.HALF.HI) {
+ super->subAction = 1;
+ super->direction = 0x80;
+ super->animationState = 0x80;
+ super->speed = 0xc0;
+ super->x.HALF.HI = gRoomControls.origin_x + 0xa8;
+ super->y.HALF.HI = gRoomControls.origin_y - 0x40;
+ this->unk_78 = 0x8000;
+ this->unk_7a = 0x8000;
+ }
+ }
+}
+
+void Enemy64_Action1_SubAction1(Enemy64Entity* this) {
+ sub_08049998(this, ((0x100 - super->direction) & 0xff) << 8);
+ if ((gRoomControls.origin_y + 0x40) < super->y.HALF.HI) {
+ super->action = 2;
+ super->subAction = 0;
+ }
+}
+
+void Enemy64_Action2(Enemy64Entity* this) {
+ Enemy64_Action2_SubActions[super->subAction](this);
+ UpdateAnimationSingleFrame(super);
+}
+
+void Enemy64_Action2_SubAction0(Enemy64Entity* this) {
+ u16 uVar1;
+ u16* puVar2;
+
+ super->subAction = 1;
+ super->speed = 0x120;
+ this->unk_6e = 0;
+ if ((s32)(super->x.HALF.HI - (u32)gRoomControls.origin_x) < 0xa8) {
+ this->unk_80 = 0xd8;
+ this->unk_74 = 0x100;
+ } else {
+ this->unk_80 = 0x78;
+ this->unk_74 = 0xff00;
+ }
+ this->unk_80 += gRoomControls.origin_x;
+ if ((s32)(super->y.HALF.HI - (u32)gRoomControls.origin_y) < 0x80) {
+ this->unk_82 = 0xb0;
+ } else {
+ this->unk_82 = 0x50;
+ this->unk_74 *= -1;
+ }
+ this->unk_82 += gRoomControls.origin_y;
+ Enemy64_Action2_SubAction1(this);
+}
+
+void Enemy64_Action2_SubAction1(Enemy64Entity* this) {
+ u32 tmp = sub_080045DA(this->unk_80 - super->x.HALF.HI, this->unk_82 - super->y.HALF.HI);
+ if (4 < (((super->direction - tmp) + 2) & 0xff)) {
+ if (((tmp - super->direction) & 0x80) != 0) {
+ super->direction--;
+ } else {
+ super->direction++;
+ }
+ }
+ sub_08049998(this, ((0x100 - super->direction) & 0xff) << 8);
+ if (EntityWithinDistance(super, this->unk_80, this->unk_82, (super->speed >> 0x10) + 0x10)) {
+ super->subAction = 2;
+ super->speed = 0xc0;
+ this->unk_7e = 0x100;
+ this->unk_76 = (u16)super->direction << 8;
+ }
+}
+
+void Enemy64_Action2_SubAction2(Enemy64Entity* this) {
+ u32 iVar1;
+ u32 uVar2;
+ u32 uVar3;
+
+ iVar1 = this->unk_76 += this->unk_74;
+ uVar2 = iVar1 * 0x10000;
+ super->direction = (u8)(uVar2 >> 0x18);
+ if (((uVar2 >> 0x18 & 0x1f) == 0) &&
+ (uVar3 = CalculateDirectionTo(super->x.HALF.HI, super->y.HALF.HI, gRoomControls.origin_x + 0xa8,
+ gRoomControls.origin_y + 0x80),
+ ((((uVar3 + 2) & 0x1c) - (super->direction >> 3)) & 0xf) == 8)) {
+ super->subAction = 4;
+ super->actionDelay = 0x3c;
+ super->field_0xf = 7;
+ }
+ sub_08049944(this);
+ sub_08047EA4(super, ((0x100 - super->direction) & 0xff) << 8);
+}
+
+void Enemy64_Action2_SubAction3(Enemy64Entity* this) {
+ s32 iVar1;
+ u32 uVar2;
+
+ iVar1 = this->unk_76 += this->unk_74;
+ uVar2 = iVar1 * 0x10000;
+ super->direction = (uVar2 >> 0x18);
+ if (super->actionDelay == 0) {
+ if ((uVar2 >> 0x18 & 0x1f) == 0) {
+ super->subAction = 4;
+ super->actionDelay = 0x5a;
+ }
+ } else {
+ if (sub_08049A8C(this)) {
+ Entity* projectile = CreateProjectile(GYORG_MALE_ENERGY_PROJECTILE);
+ if (projectile != NULL) {
+ projectile->collisionLayer = 2;
+ projectile->parent = super;
+ UpdateSpriteForCollisionLayer(projectile);
+ }
+ }
+ }
+ sub_08049944(this);
+ sub_08047EA4(super, ((0x100 - super->direction) & 0xff) << 8);
+}
+
+void Enemy64_Action2_SubAction4(Enemy64Entity* this) {
+ sub_08049998(this, ((0x100 - super->direction) & 0xff) << 8);
+ if (--super->actionDelay == 0) {
+ if (--super->field_0xf == 0) {
+ super->subAction = 5;
+ super->speed += 0x40;
+ } else {
+ super->subAction = 3;
+ super->actionDelay = 0xa;
+ }
+ } else if (super->actionDelay == 0x50) {
+ Entity* enemy = CreateEnemy(GYORG_MALE_EYE, Random() & 3);
+ if (enemy != NULL) {
+ enemy->parent = super;
+ }
+ }
+}
+
+void Enemy64_Action2_SubAction5(Enemy64Entity* this) {
+ sub_08049998(this, ((0x100 - super->direction) & 0xff) << 8);
+ if (EntityWithinDistance(super, gRoomControls.origin_x + 0xa8, gRoomControls.origin_y + 0x80, 0x70) == FALSE) {
+ super->action = 3;
+ super->subAction = 0;
+ }
+}
+
+void Enemy64_Action3(Enemy64Entity* this) {
+ Enemy64_Action3_SubActions[super->subAction](this);
+ UpdateAnimationSingleFrame(super);
+}
+
+void Enemy64_Action3_SubAction0(Enemy64Entity* this) {
+ u32 tmp = sub_080045DA(gRoomControls.origin_x + 0xa8 - super->x.HALF.HI,
+ gRoomControls.origin_y + 0x80 - super->y.HALF.HI);
+ if (tmp != super->direction) {
+ if (((tmp - super->direction) & 0x80) != 0) {
+ super->direction--;
+ } else {
+ super->direction++;
+ }
+ } else {
+ super->subAction = 1;
+ super->speed = 0x180;
+ }
+ sub_08049944(this);
+ sub_08047EA4(super, ((0x100 - super->direction) & 0xff) << 8);
+}
+
+void Enemy64_Action3_SubAction1(Enemy64Entity* this) {
+ if (EntityWithinDistance(super, gRoomControls.origin_x + 0xa8, gRoomControls.origin_y + 0x80, 0x28)) {
+ super->subAction = 2;
+ super->actionDelay = 0x2d;
+ this->unk_74 = gUnk_080D29B8[Random() & 7] << 0x18 >> 0x18;
+ this->unk_76 = super->direction << 8;
+ }
+ sub_08049998(this, ((0x100 - super->direction) & 0xff) << 8);
+}
+
+void Enemy64_Action3_SubAction2(Enemy64Entity* this) {
+ this->unk_76 += this->unk_74;
+ super->direction = this->unk_76 >> 8;
+ sub_08049998(this, ((0x100 - super->direction) & 0xff) << 8);
+ if (--super->actionDelay == 0) {
+ super->subAction = 3;
+ super->actionDelay = 0x1e;
+ }
+}
+
+void Enemy64_Action3_SubAction3(Enemy64Entity* this) {
+ sub_08049998(this, ((0x100 - super->direction) & 0xff) << 8);
+ if (--super->actionDelay == 0) {
+ super->action = 2;
+ super->subAction = 0;
+ }
+}
+
+void Enemy64_Action4(Enemy64Entity* this) {
+ Enemy64_Action4_SubActions[super->subAction](this);
+ UpdateAnimationSingleFrame(super);
+}
+
+void Enemy64_Action4_SubAction0(Enemy64Entity* this) {
+ SoundReq(SFX_BOSS_DIE);
+ if (sub_08079F8C() && gPlayerEntity.z.HALF.HI == 0) {
+ SetPlayerControl(CONTROL_2);
+ super->subAction = 2;
+ super->actionDelay = 0x1e;
+ } else {
+ super->subAction = 1;
+ }
+ sub_08049944(this);
+}
+
+void Enemy64_Action4_SubAction1(Enemy64Entity* this) {
+ if (sub_08079F8C() && gPlayerEntity.z.HALF.HI == 0) {
+ SetPlayerControl(CONTROL_2);
+ super->subAction = 2;
+ super->actionDelay = 1;
+ }
+ sub_08049944(this);
+}
+
+void Enemy64_Action4_SubAction2(Enemy64Entity* this) {
+ if (--super->actionDelay == 0) {
+ super->subAction = 3;
+ super->actionDelay = 0xb4;
+ super->speed = 0x100;
+ super->direction -= 0x40;
+ }
+ sub_08049944(this);
+}
+
+void Enemy64_Action4_SubAction3(Enemy64Entity* this) {
+ sub_08049AB0(this);
+ if (--super->actionDelay == 0) {
+ super->actionDelay = 0x1e;
+ super->subAction = 4;
+ super->speed = 0x400;
+ super->direction = super->animationState;
+ SoundReq(SFX_BOSS_DIE);
+ } else {
+ super->direction ^= 0x80;
+ sub_08049B20(this);
+ }
+ sub_08049944(this);
+}
+
+void Enemy64_Action4_SubAction4(Enemy64Entity* this) {
+ sub_08049AB0(this);
+ sub_08049998(this, ((0x100 - super->direction) & 0xff) << 8);
+ if (--super->actionDelay == 0) {
+ super->subAction = 5;
+ SetFade(5, 0x10);
+ }
+}
+
+void Enemy64_Action4_SubAction5(Enemy64Entity* this) {
+ Entity* entity;
+ sub_08049944(this);
+ if (gFadeControl.active == 0) {
+ super->subAction = 6;
+ super->spriteSettings.draw = 0;
+ entity = super->child;
+ entity->flags &= 0x7f;
+ entity->spriteSettings.draw = 0;
+ entity = entity->child;
+ entity->flags &= 0x7f;
+ entity->spriteSettings.draw = 0;
+ entity = entity->child;
+ entity->flags &= 0x7f;
+ entity->spriteSettings.draw = 0;
+ entity = &gPlayerEntity;
+ entity->x.HALF.HI = gRoomControls.origin_x + 0xa8;
+ entity->y.HALF.HI = gRoomControls.origin_y + 0x80;
+ entity->animationState = 0;
+ sub_080809D4();
+ SetFade(4, 4);
+ }
+}
+
+void Enemy64_Action4_SubAction6(Enemy64Entity* this) {
+ if (gFadeControl.active == 0) {
+ super->subAction = 7;
+ super->actionDelay = 0xa0;
+ SoundReq(SFX_SECRET);
+ SetFlag(0x7c);
+ SetPlayerControl(CONTROL_1);
+ }
+}
+
+void Enemy64_Action4_SubAction7(Enemy64Entity* this) {
+ if (--super->actionDelay == 0) {
+ DeleteThisEntity();
+ } else if (super->actionDelay == 0x10) {
+ sub_0807B7D8(0x36, 0xca, 1);
+ SetTile(0x4081, 0xca, 2);
+ SoundReq(SFX_HEART_GET);
+ } else if (super->actionDelay == 0x18) {
+ sub_0807B7D8(0x36, 0x8a, 1);
+ SetTile(0x4081, 0x8a, 2);
+ SoundReq(SFX_HEART_GET);
+ } else if (super->actionDelay == 0x20) {
+ sub_0807B7D8(0x36, 0x4a, 1);
+ SetTile(0x4081, 0x4a, 2);
+ SoundReq(SFX_HEART_GET);
+ } else if (super->actionDelay == 0x28) {
+ sub_0807B7D8(0x36, 10, 1);
+ SetTile(0x4081, 10, 2);
+ SoundReq(SFX_HEART_GET);
+ }
+}
+
+void sub_08049944(Enemy64Entity* this) {
+ this->unk_7c = (this->unk_7c << 1 & 0x7f) | (this->unk_7c & 0x80);
+ if (EntityWithinDistance(super, gPlayerEntity.x.HALF.HI, gPlayerEntity.y.HALF.HI, 0x20)) {
+ gPlayerState.field_0x14 = 1;
+ if (gPlayerEntity.z.HALF.HI == 0) {
+ gPlayerState.flags |= 2;
+ this->unk_7c |= 1;
+ }
+ }
+}
+
+void sub_08049998(Enemy64Entity* this, u32 param_2) {
+ s32 tmpX;
+ s32 tmpY;
+
+ sub_08049944(this);
+ sub_08047EA4(super, param_2);
+ tmpX = super->x.HALF.HI;
+ tmpY = super->y.HALF.HI;
+ LinearMoveAngle(super, super->speed, super->direction);
+ if (((this->unk_7c & 1) != 0) && sub_08079F8C()) {
+ gPlayerEntity.x.HALF.HI = (super->x.HALF.HI - tmpX) + gPlayerEntity.x.HALF.HI;
+ gPlayerEntity.y.HALF.HI = (super->y.HALF.HI - tmpY) + gPlayerEntity.y.HALF.HI;
+ }
+}
+
+void sub_080499F0(Enemy64Entity* this) {
+ u32 tmp;
+
+ if ((((super->action != 0) && (gPlayerEntity.z.HALF.HI == 0)) && (sub_08079F8C())) && ((this->unk_7c & 1) == 0)) {
+ if (EntityWithinDistance(&gPlayerEntity, super->x.HALF.HI, super->y.HALF.HI, 0x24) &&
+ ((this->unk_7c & 2) == 0)) {
+ tmp = sub_080045DA((s32)gPlayerEntity.x.HALF.HI - super->x.HALF.HI,
+ (s32)gPlayerEntity.y.HALF.HI - super->y.HALF.HI);
+ gPlayerEntity.x.WORD = super->x.WORD + gSineTable[tmp] * 0x2400;
+ gPlayerEntity.y.WORD = super->y.WORD + gSineTable[tmp + 0x40] * -0x2400;
+ }
+ this->unk_7c = 0;
+ }
+}
+
+bool32 sub_08049A8C(Enemy64Entity* this) {
+ if (--super->actionDelay == 0 && (Random() & 0xf) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+void sub_08049AB0(Enemy64Entity* this) {
+ u32 rand;
+
+ if ((++super->field_0xf & 0xf) == 0) {
+ Entity* effect = CreateFx(super, FX_GIANT_EXPLOSION3, 0);
+ if (effect != NULL) {
+ rand = Random();
+ effect->x.HALF.HI += ((rand & 0x30) - 0x18);
+ effect->y.HALF.HI += (((rand >> 8) & 0x30) - 0x18);
+ effect->spritePriority.b0 = 3;
+ effect->collisionLayer = 2;
+ UpdateSpriteForCollisionLayer(effect);
+ }
+ }
+}
+
+void sub_08049B20(Enemy64Entity* this) {
+ s32 tmpX;
+ s32 tmpY;
+
+ sub_08049944(this);
+ tmpX = super->x.HALF.HI;
+ tmpY = super->y.HALF.HI;
+ LinearMoveAngle(super, super->speed, super->direction);
+ if (((this->unk_7c & 1) != 0) && sub_08079F8C()) {
+ gPlayerEntity.x.HALF.HI = (super->x.HALF.HI - tmpX) + gPlayerEntity.x.HALF.HI;
+ gPlayerEntity.y.HALF.HI = (super->y.HALF.HI - tmpY) + gPlayerEntity.y.HALF.HI;
+ }
+}
+
+void (*const Enemy64_Actions[])(Enemy64Entity*) = {
+ Enemy64_Init, Enemy64_Action1, Enemy64_Action2, Enemy64_Action3, Enemy64_Action4,
+};
+void (*const Enemy64_Action1_SubActions[])(Enemy64Entity*) = {
+ Enemy64_Action1_SubAction0,
+ Enemy64_Action1_SubAction1,
+};
+void (*const Enemy64_Action2_SubActions[])(Enemy64Entity*) = {
+ Enemy64_Action2_SubAction0, Enemy64_Action2_SubAction1, Enemy64_Action2_SubAction2,
+ Enemy64_Action2_SubAction3, Enemy64_Action2_SubAction4, Enemy64_Action2_SubAction5,
+};
+void (*const Enemy64_Action3_SubActions[])(Enemy64Entity*) = {
+ Enemy64_Action3_SubAction0,
+ Enemy64_Action3_SubAction1,
+ Enemy64_Action3_SubAction2,
+ Enemy64_Action3_SubAction3,
+};
+const u8 gUnk_080D29B8[] = {
+ 144, 112, 56, 200, 0, 0, 0, 0,
+};
+void (*const Enemy64_Action4_SubActions[])(Enemy64Entity*) = {
+ Enemy64_Action4_SubAction0, Enemy64_Action4_SubAction1, Enemy64_Action4_SubAction2, Enemy64_Action4_SubAction3,
+ Enemy64_Action4_SubAction4, Enemy64_Action4_SubAction5, Enemy64_Action4_SubAction6, Enemy64_Action4_SubAction7,
+};