mirror of
https://github.com/zeldaret/tmc
synced 2026-06-25 18:04:49 -04:00
443 lines
10 KiB
C
443 lines
10 KiB
C
/**
|
|
* @file helmasaur.c
|
|
* @ingroup Enemies
|
|
*
|
|
* @brief Helmasaur enemy
|
|
*/
|
|
|
|
#include "enemy.h"
|
|
#include "object.h"
|
|
#include "functions.h"
|
|
#include "collision.h"
|
|
|
|
extern u32 sub_0804A024(Entity*, u32, u32);
|
|
|
|
void sub_0802C18C(Entity*);
|
|
void sub_0802C218(Entity*);
|
|
void sub_0802C1C0(Entity*);
|
|
u32 sub_0802C020(Entity*);
|
|
void sub_0802C058(Entity*, u32);
|
|
bool32 sub_0802C06C(Entity*);
|
|
void sub_0802C1CC(Entity*);
|
|
bool32 sub_0802C0E8(Entity*);
|
|
|
|
extern void (*const Helmasaur_Functions[])(Entity*);
|
|
extern void (*const gUnk_080CD3FC[])(Entity*);
|
|
extern void (*const gUnk_080CD408[])(Entity*);
|
|
extern void (*const gUnk_080CD42C[])(Entity*);
|
|
extern void (*const gUnk_080CD438[])(Entity*);
|
|
extern void (*const gUnk_080CD450[])(Entity*);
|
|
extern const s8 gUnk_080CD45C[];
|
|
extern const s8 gUnk_080CD464[];
|
|
|
|
void Helmasaur(Entity* this) {
|
|
if (this->type == 0) {
|
|
EnemyFunctionHandler(this, Helmasaur_Functions);
|
|
SetChildOffset(this, 0, 1, -0x10);
|
|
} else {
|
|
gUnk_080CD3FC[this->action](this);
|
|
}
|
|
}
|
|
|
|
void Helmasaur_OnTick(Entity* this) {
|
|
gUnk_080CD408[this->action](this);
|
|
}
|
|
|
|
void Helmasaur_OnCollision(Entity* this) {
|
|
if (this->hitType != 0x19) {
|
|
switch (this->contactFlags & 0x7f) {
|
|
case 0:
|
|
case 2:
|
|
case 3:
|
|
if (this->action == 4) {
|
|
this->knockbackDuration = 0;
|
|
sub_0802C218(this);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (this->confusedTime != 0) {
|
|
Create0x68FX(this, FX_STARS);
|
|
}
|
|
|
|
EnemyFunctionHandlerAfterCollision(this, Helmasaur_Functions);
|
|
}
|
|
|
|
void Helmasaur_OnGrabbed(Entity* this) {
|
|
if (this->hitType != 0x19) {
|
|
if (sub_0806F520(this)) {
|
|
gUnk_080CD42C[this->subAction](this);
|
|
}
|
|
} else if (2 < this->subAction || sub_0806F520(this)) {
|
|
gUnk_080CD438[this->subAction](this);
|
|
}
|
|
}
|
|
|
|
void sub_0802BC74(Entity* this) {
|
|
sub_0802C1C0(this);
|
|
this->subAction = 1;
|
|
this->gustJarTolerance = 60;
|
|
this->animationState = AnimationStateFlip90(gPlayerEntity.animationState >> 1);
|
|
InitializeAnimation(this, this->animationState);
|
|
}
|
|
|
|
void sub_0802BCA0(Entity* this) {
|
|
sub_0806F4E8(this);
|
|
}
|
|
|
|
void sub_0802BCA8(Entity* this) {
|
|
if (this->hitType != 0x19) {
|
|
Entity* ent;
|
|
|
|
this->action = 7;
|
|
this->timer = 90;
|
|
this->zVelocity = Q_16_16(1.5);
|
|
this->hitType = 0x19;
|
|
this->gustJarState = this->gustJarState & 0xfb;
|
|
this->gustJarFlags = 0x12;
|
|
ent = CreateEnemy(HELMASAUR, 1);
|
|
if (ent != NULL) {
|
|
ent->animationState = this->animationState;
|
|
CopyPosition(this, ent);
|
|
}
|
|
InitializeAnimation(this, this->animationState + 4);
|
|
}
|
|
}
|
|
|
|
void sub_0802BCFC(Entity* this) {
|
|
this->subAction = 1;
|
|
this->gustJarTolerance = 60;
|
|
}
|
|
|
|
void sub_0802BD08(Entity* this) {
|
|
sub_0806F3E4(this);
|
|
}
|
|
|
|
void sub_0802BD10(Entity* this) {
|
|
COLLISION_OFF(this);
|
|
UpdateAnimationVariableFrames(this, 2);
|
|
}
|
|
|
|
void nullsub_145(Entity* this) {
|
|
/* ... */
|
|
}
|
|
|
|
void sub_0802BD28(Entity* this) {
|
|
if (this->flags & ENT_COLLIDE) {
|
|
COLLISION_ON(this);
|
|
this->gustJarState &= ~0x4;
|
|
} else {
|
|
this->health = 0;
|
|
}
|
|
}
|
|
|
|
void sub_0802BD54(Entity* this) {
|
|
sub_0804A720(this);
|
|
this->action = 1;
|
|
this->field_0x78.HALF.LO = Random();
|
|
this->gustJarTolerance = 60;
|
|
this->field_0x78.HALF.HI = 0xff;
|
|
this->direction = DirectionRound(Random());
|
|
this->animationState = this->direction >> 3;
|
|
InitializeAnimation(this, this->animationState);
|
|
}
|
|
|
|
void sub_0802BD8C(Entity* this) {
|
|
if (this->timer) {
|
|
this->timer--;
|
|
} else {
|
|
u32 direction;
|
|
|
|
if (sub_08049FDC(this, 1)) {
|
|
direction = sub_0804A024(this, 1, 0x10);
|
|
if (direction != 0xff && direction != this->field_0x78.HALF.HI) {
|
|
sub_0802C058(this, direction);
|
|
return;
|
|
}
|
|
}
|
|
|
|
direction = sub_0802C020(this);
|
|
if (direction != this->direction) {
|
|
sub_0802C058(this, direction);
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_0802BDE0(Entity* this) {
|
|
if (sub_0802C06C(this)) {
|
|
this->action = 3;
|
|
this->timer = 60;
|
|
this->field_0x78.HALF.HI = 0xff;
|
|
} else {
|
|
this->action = 1;
|
|
this->timer = (Random() & 0xf) + 0xf;
|
|
this->field_0x78.HALF.HI = this->direction;
|
|
}
|
|
}
|
|
|
|
void sub_0802BE18(Entity* this) {
|
|
UpdateAnimationVariableFrames(this, 2);
|
|
if (--this->timer == 0) {
|
|
this->action = 4;
|
|
this->timer = 0x1e;
|
|
this->speed = 0x300;
|
|
} else {
|
|
sub_0802C18C(this);
|
|
}
|
|
}
|
|
|
|
void sub_0802BE48(Entity* this) {
|
|
if (!ProcessMovement2(this)) {
|
|
sub_0802C218(this);
|
|
InitScreenShake(8, 0);
|
|
} else {
|
|
GetNextFrame(this);
|
|
sub_0802C1CC(this);
|
|
if (sub_0802C0E8(this)) {
|
|
this->action = 5;
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_0802BE80(Entity* this) {
|
|
this->speed -= 0x20;
|
|
if (0xff < this->speed) {
|
|
sub_0802C1CC(this);
|
|
}
|
|
|
|
if (this->speed > 0) {
|
|
ProcessMovement2(this);
|
|
sub_0802C18C(this);
|
|
} else {
|
|
sub_0802C1C0(this);
|
|
this->timer += 30;
|
|
}
|
|
}
|
|
|
|
void sub_0802BEBC(Entity* this) {
|
|
this->direction ^= 0x10;
|
|
ProcessMovement2(this);
|
|
this->direction ^= 0x10;
|
|
if (!sub_080044EC(this, Q_16_16(0.125))) {
|
|
sub_0802C1C0(this);
|
|
}
|
|
}
|
|
|
|
void sub_0802BEEC(Entity* this) {
|
|
if (this->timer) {
|
|
if ((--this->timer & 0x1f) == 0) {
|
|
this->animationState ^= 2;
|
|
this->direction = this->animationState << 3;
|
|
InitializeAnimation(this, this->animationState + 4);
|
|
}
|
|
} else if (!GravityUpdate(this, Q_8_8(28.0))) {
|
|
this->action = 8;
|
|
this->timer = 30;
|
|
this->speed = 0x120;
|
|
}
|
|
}
|
|
|
|
void sub_0802BF3C(Entity* this) {
|
|
ProcessMovement0(this);
|
|
GetNextFrame(this);
|
|
if (--this->timer == 0) {
|
|
u32 sprite;
|
|
|
|
this->timer = 30;
|
|
this->direction = sub_0802C020(this);
|
|
sprite = this->direction >> 3;
|
|
if (sprite != this->animationState) {
|
|
this->animationState = sprite;
|
|
InitializeAnimation(this, sprite + 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_0802BF78(Entity* this) {
|
|
this->action = 1;
|
|
this->flags2 = 4;
|
|
this->gustJarFlags = 1;
|
|
this->direction = this->animationState << 3;
|
|
InitializeAnimation(this, this->animationState + 8);
|
|
}
|
|
|
|
void sub_0802BF98(Entity* this) {
|
|
if (sub_0806F520(this)) {
|
|
gUnk_080CD450[this->subAction](this);
|
|
} else {
|
|
this->action = 2;
|
|
this->timer = 30;
|
|
COLLISION_OFF(this);
|
|
}
|
|
}
|
|
|
|
void sub_0802BFD0(Entity* this) {
|
|
this->subAction = 2;
|
|
}
|
|
|
|
void sub_0802BFD8(Entity* this) {
|
|
sub_0806F4E8(this);
|
|
}
|
|
|
|
void sub_0802BFE0(Entity* this) {
|
|
if (sub_0806F3E4(this)) {
|
|
DeleteEntity(this);
|
|
}
|
|
}
|
|
|
|
void sub_0802BFF4(Entity* this) {
|
|
this->spriteSettings.draw ^= 1;
|
|
if (--this->timer == 0) {
|
|
DeleteEntity(this);
|
|
}
|
|
}
|
|
|
|
u32 sub_0802C020(Entity* this) {
|
|
u32 uVar1 = Random();
|
|
|
|
if (sub_08049FA0(this) || (uVar1 & 1))
|
|
return DirectionRound(uVar1);
|
|
|
|
return (sub_08049EE4(this) + (uVar1 >> 0x10 & 1) * 4) & 0x18;
|
|
}
|
|
|
|
void sub_0802C058(Entity* this, u32 param_2) {
|
|
this->action = 2;
|
|
this->direction = param_2;
|
|
this->animationState = param_2 >> 3;
|
|
InitializeAnimation(this, this->animationState);
|
|
}
|
|
|
|
bool32 sub_0802C06C(Entity* this) {
|
|
u32 x = this->x.HALF.HI + this->hitbox->offset_x;
|
|
u32 y = this->y.HALF.HI + this->hitbox->offset_y;
|
|
u32 xdiff = gUnk_080CD45C[(this->direction >> 2) + 0];
|
|
u32 ydiff = gUnk_080CD45C[(this->direction >> 2) + 1];
|
|
|
|
u8* layer = this->collisionLayer == 2 ? gMapTop.collisionData : gMapBottom.collisionData;
|
|
|
|
u32 i;
|
|
for (i = 0; i < 8; i++) {
|
|
x += xdiff;
|
|
y += ydiff;
|
|
if (IsTileCollision(layer, x, y, 0))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool32 sub_0806FC24(u32, u32);
|
|
|
|
bool32 sub_0802C0E8(Entity* this) {
|
|
if (--this->timer == 0) {
|
|
return TRUE;
|
|
} else {
|
|
const s8* ptr = &gUnk_080CD45C[this->direction >> 2];
|
|
s32 x = this->x.HALF.HI + this->hitbox->offset_x + ptr[0] * 6;
|
|
s32 y = this->y.HALF.HI + this->hitbox->offset_y + ptr[1] * 6;
|
|
|
|
u8* layer = this->collisionLayer == 2 ? gMapTop.collisionData : gMapBottom.collisionData;
|
|
u32 ret = FALSE;
|
|
if (!sub_0806FC24(TILE(x, y), 9)) {
|
|
if (IsTileCollision(layer, x, y, 0)) {
|
|
ret = 1;
|
|
} else {
|
|
ret = 0;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
void sub_0802C18C(Entity* this) {
|
|
this->field_0x78.HALF.LO--;
|
|
if ((this->field_0x78.HALF.LO & 7) == 0) {
|
|
Entity* ent = CreateObject(SPECIAL_FX, 0x11, 0x40);
|
|
if (ent != NULL) {
|
|
PositionRelative(this, ent, 0, Q_16_16(1.0));
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_0802C1C0(Entity* this) {
|
|
this->action = 1;
|
|
this->timer = 30;
|
|
}
|
|
|
|
void sub_0802C1CC(Entity* this) {
|
|
const s8* ptr = &gUnk_080CD464[this->animationState << 2];
|
|
sub_08008796(this, 9, this->x.HALF.HI + ptr[0], this->y.HALF.HI + ptr[1]);
|
|
sub_08008796(this, 9, this->x.HALF.HI + ptr[2], this->y.HALF.HI + ptr[3]);
|
|
}
|
|
|
|
void sub_0802C218(Entity* this) {
|
|
this->action = 6;
|
|
this->speed = Q_8_8(0.875);
|
|
this->zVelocity = Q_16_16(1.5);
|
|
}
|
|
|
|
// clang-format off
|
|
void (*const Helmasaur_Functions[])(Entity*) = {
|
|
Helmasaur_OnTick,
|
|
Helmasaur_OnCollision,
|
|
GenericKnockback,
|
|
GenericDeath,
|
|
GenericConfused,
|
|
Helmasaur_OnGrabbed,
|
|
};
|
|
|
|
void (*const gUnk_080CD3FC[])(Entity*) = {
|
|
sub_0802BF78,
|
|
sub_0802BF98,
|
|
sub_0802BFF4,
|
|
};
|
|
|
|
void (*const gUnk_080CD408[])(Entity*) = {
|
|
sub_0802BD54,
|
|
sub_0802BD8C,
|
|
sub_0802BDE0,
|
|
sub_0802BE18,
|
|
sub_0802BE48,
|
|
sub_0802BE80,
|
|
sub_0802BEBC,
|
|
sub_0802BEEC,
|
|
sub_0802BF3C,
|
|
};
|
|
|
|
void (*const gUnk_080CD42C[])(Entity*) = {
|
|
sub_0802BC74,
|
|
sub_0802BCA0,
|
|
sub_0802BCA8,
|
|
};
|
|
|
|
void (*const gUnk_080CD438[])(Entity*) = {
|
|
sub_0802BCFC,
|
|
sub_0802BCA0,
|
|
sub_0802BD08,
|
|
sub_0802BD10,
|
|
nullsub_145,
|
|
sub_0802BD28,
|
|
};
|
|
|
|
void (*const gUnk_080CD450[])(Entity*) = {
|
|
sub_0802BFD0,
|
|
sub_0802BFD8,
|
|
sub_0802BFE0,
|
|
};
|
|
|
|
const s8 gUnk_080CD45C[] = {
|
|
0, -8,
|
|
8, 0,
|
|
0, 8,
|
|
-8, 0,
|
|
};
|
|
|
|
const s8 gUnk_080CD464[] = {
|
|
-3, -8, 3, -8,
|
|
8, -3, 8, 3,
|
|
-3, 8, 3, 8,
|
|
-8, -3, -8, 3,
|
|
};
|
|
// clang-format on
|