diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/enemy/enemy64.c | 523 |
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, +}; |
