Files
tmc/src/enemy/spearMoblin.c
T
2023-12-30 21:07:06 -08:00

454 lines
12 KiB
C

/**
* @file spearMoblin.c
* @ingroup Enemies
*
* @brief Spear Moblin enemy
*/
#include "enemy.h"
#include "functions.h"
typedef struct {
/*0x00*/ Entity base;
/*0x68*/ u8 unused1[18];
/*0x7a*/ u8 unk_7a;
/*0x7b*/ u8 unk_7b;
/*0x7c*/ u8 unused2[4];
/*0x80*/ u8 unk_80;
/*0x81*/ u8 unk_81;
/*0x82*/ u8 unk_82;
/*0x83*/ u8 unk_83;
} SpearMoblinEntity;
void sub_08028604(SpearMoblinEntity*);
void sub_08028754(SpearMoblinEntity*);
void sub_08028784(SpearMoblinEntity*);
void sub_080287E0(SpearMoblinEntity*);
void sub_08028728(SpearMoblinEntity*);
bool32 sub_080286CC(SpearMoblinEntity*);
bool32 sub_080288A4(SpearMoblinEntity*);
void sub_08028858(SpearMoblinEntity*);
void sub_080288C0(SpearMoblinEntity*);
bool32 sub_08028828(u32, u32);
void sub_080287B4(SpearMoblinEntity*);
extern void (*const SpearMoblin_Functions[])(SpearMoblinEntity*);
extern void (*const gUnk_080CC7A8[])(SpearMoblinEntity*);
extern const u8 gUnk_080CC7BC[];
extern const s8 gUnk_080CC7C0[];
extern const s8 gUnk_080CC7D0[];
extern const u16 gUnk_080CC7D8[];
extern const Hitbox* const gUnk_080CC944[];
void SpearMoblin(SpearMoblinEntity* this) {
EnemyFunctionHandler(super, (EntityActionArray)SpearMoblin_Functions);
EnemySetFXOffset(super, 0, 1, -0x20);
if (super->child && super->child->next) {
CopyPosition(super, super->child);
}
}
void SpearMoblin_OnTick(SpearMoblinEntity* this) {
gUnk_080CC7A8[super->action](this);
}
void SpearMoblin_OnCollision(SpearMoblinEntity* this) {
if (super->confusedTime != 0)
EnemyCreateFX(super, FX_STARS);
EnemyFunctionHandlerAfterCollision(super, SpearMoblin_Functions);
if (super->contactFlags & CONTACT_TAKE_DAMAGE) {
if (super->action != 4) {
sub_08028754(this);
} else {
if ((super->contactFlags & 0x3f) == 0) {
this->unk_7a++;
this->unk_81 = 0x16;
sub_08028784(this);
}
}
}
super->child->iframes = super->iframes;
if (super->health == 0) {
super->speed = 0;
this->unk_82 = 0;
sub_080287E0(this);
DeleteEntity(super->child);
super->child = NULL;
}
}
void SpearMoblin_OnGrabbed(SpearMoblinEntity* this) {
/* ... */
}
void sub_08028314(SpearMoblinEntity* this) {
Entity* pEVar2;
sub_0804A720(super);
super->action = 1;
super->animationState = 0;
this->unk_7b = 0;
this->unk_80 = 0;
this->unk_83 = 0;
this->unk_81 = 0;
this->unk_7a = 0;
this->unk_82 = 1;
if (super->timer) {
super->animationState = super->type2 << 1;
super->timer = 30;
super->speed = 0x80;
super->direction = super->animationState << 2;
sub_080287E0(this);
} else {
super->animationState = 0x10;
sub_08028604(this);
}
pEVar2 = CreateProjectile(MOBLIN_SPEAR);
if (pEVar2 != NULL) {
pEVar2->parent = super;
super->child = pEVar2;
}
}
void sub_08028378(SpearMoblinEntity* this) {
if (this->unk_81 != 0) {
this->unk_81--;
}
if (--super->timer == 0) {
if (++this->unk_80 >= 0x10) {
sub_08028728(this);
} else {
sub_08028604(this);
}
} else {
if (sub_080286CC(this)) {
this->unk_7b |= 1;
}
if (sub_080288A4(this)) {
sub_0800417E(super, super->collisions);
super->animationState = DirectionRoundUp(super->direction) >> 2;
this->unk_83++;
sub_080287E0(this);
}
}
if (super->subtimer >= 0xc) {
if (this->unk_7b != 0) {
sub_08028754(this);
}
} else {
super->subtimer++;
}
sub_08028858(this);
}
void sub_08028420(SpearMoblinEntity* this) {
if (--super->timer == 0) {
super->action = 3;
this->unk_82 = 0;
this->unk_80 = 0;
super->animationState = 0x10;
sub_08028604(this);
} else {
if (sub_080286CC(this)) {
this->unk_7b |= 1;
}
}
if (super->subtimer >= 0xc) {
if (this->unk_7b != 0) {
sub_08028754(this);
}
} else {
super->subtimer++;
}
sub_08028858(this);
}
void sub_08028488(SpearMoblinEntity* this) {
if (--super->timer == 0) {
switch (this->unk_82) {
case 3:
super->action = 4;
super->speed = 0x180;
super->direction = sub_08049F84(super, 1);
EnqueueSFX(SFX_EM_MOBLIN_SPEAR);
break;
case 2:
super->action = 2;
super->speed = 0;
super->timer = (Random() & 7) * 3 + 64;
break;
case 4:
super->direction = (super->direction + 0x10) & DirectionWest;
/* fallthrough */
case 1:
default:
super->action = 1;
this->unk_82 = 1;
super->speed = 0x80;
super->timer = (Random() & 7) * 3 + 0x22;
break;
}
super->subtimer = 0;
super->animationState = DirectionRoundUp(super->direction) >> 2;
sub_080287E0(this);
}
sub_08028858(this);
}
void sub_08028528(SpearMoblinEntity* this) {
Entity* entity = sub_08049DF4(1);
const Hitbox* box;
if (entity == NULL) {
super->subtimer = 0;
sub_08028728(this);
} else {
sub_080288C0(this);
box = gUnk_080CC944[super->animationState >> 1];
super->hitbox->offset_x = box->offset_x;
super->hitbox->offset_y = box->offset_y;
super->hitbox->width = box->width;
super->hitbox->height = box->height;
if (this->unk_7a != 0) {
this->unk_7a = 0;
this->unk_81 = 0x16;
sub_08028784(this);
} else {
if (++super->timer == 0x20) {
u32 direction;
super->timer = 0;
direction = GetFacingDirection(super, entity);
if (sub_08028828(super->direction, direction)) {
super->direction = direction;
}
}
if ((super->timer & 7) == 0) {
EnqueueSFX(SFX_F0);
CreateFx(super, FX_DEATH, 0x40);
}
if (++this->unk_7b == 0x80) {
this->unk_7a++;
}
}
if (0x20 < this->unk_7b) {
ProcessMovement0(super);
}
GetNextFrame(super);
}
}
void sub_08028604(SpearMoblinEntity* this) {
u32 iVar3;
super->subtimer = 0;
if (this->unk_82 == 1) {
super->timer = gUnk_080CC7BC[Random() & 3];
super->speed = 0x80;
if (sub_08049FA0(super) != 0) {
u32 rand = Random();
u32 tmp;
tmp = gUnk_080CC7D0[rand & 7] + 0x18;
super->direction = DirectionRound(tmp + super->direction);
iVar3 = Direction8ToAnimationState(super->direction);
} else {
iVar3 = sub_08049EE4(super);
if (this->unk_83 == 0) {
u32 rand = Random();
iVar3 += gUnk_080CC7C0[rand & 0xf];
} else {
u32 rand = Random();
iVar3 += gUnk_080CC7C0[rand & 7];
super->timer = super->timer + 0x10;
this->unk_83--;
}
super->direction = (iVar3 + 4U) & DirectionWest;
iVar3 = Direction8ToAnimationState(super->direction);
}
} else {
super->timer = 12;
super->speed = 0;
iVar3 = Direction8ToAnimationState(super->direction);
}
if (iVar3 != super->animationState) {
super->animationState = iVar3;
sub_080287E0(this);
}
}
bool32 sub_080286CC(SpearMoblinEntity* this) {
if (this->unk_81 == 0) {
Entity* entity = sub_08049DF4(1);
if (entity != NULL) {
if (this->unk_82 == 2 && sub_0806FC80(super, entity, 0x30))
return TRUE;
if (sub_0806FC80(super, entity, 0x40) &&
DirectionRoundUp(GetFacingDirection(super, entity)) >> 2 == super->animationState)
return TRUE;
}
}
return FALSE;
}
void sub_08028728(SpearMoblinEntity* this) {
super->animationState = DirectionRoundUp(super->direction) >> 2;
super->direction = super->animationState << 2;
this->unk_83 >>= 1;
sub_080287B4(this);
this->unk_82 = 2;
}
void sub_08028754(SpearMoblinEntity* this) {
super->direction = sub_08049F84(super, 1);
super->animationState = DirectionRoundUp(super->direction) >> 2;
this->unk_83 = 0;
sub_080287B4(this);
this->unk_82 = 3;
}
void sub_08028784(SpearMoblinEntity* this) {
super->animationState = DirectionRoundUp(super->direction) >> 2;
super->direction = super->animationState << 2;
this->unk_83 = 0;
sub_080287B4(this);
super->timer <<= 1;
this->unk_82 = 4;
}
void sub_080287B4(SpearMoblinEntity* this) {
super->action = 3;
super->timer = 32;
super->subtimer = 0;
this->unk_80 = 0;
this->unk_7b = 0;
super->speed = 0;
this->unk_82 = 0;
sub_080287E0(this);
}
void sub_080287E0(SpearMoblinEntity* this) {
u32 sprite = super->animationState >> 1;
switch (this->unk_82) {
case 0:
/* ... */
break;
case 1:
case 4:
sprite += 4;
break;
case 3:
sprite += 8;
break;
case 2:
sprite += 0xc;
break;
}
InitializeAnimation(super, sprite);
}
bool32 sub_08028828(u32 arg0, u32 arg1) {
if (DirectionRoundUp(arg1) == DirectionRoundUp(arg0)) {
u32 angle1 = (arg1 + 5) & 7;
u32 angle0 = (arg0 + 5) & 7;
if (angle1 < 3 && angle0 < 3)
return TRUE;
}
return FALSE;
}
void sub_08028858(SpearMoblinEntity* this) {
const Hitbox* box;
sub_080288C0(this);
box = gUnk_080CC944[super->animationState >> 1];
super->hitbox->offset_x = box->offset_x;
super->hitbox->offset_y = box->offset_y;
super->hitbox->width = box->width;
super->hitbox->height = box->height;
if (this->unk_82 == 0) {
super->speed = 0;
}
ProcessMovement0(super);
GetNextFrame(super);
}
bool32 sub_080288A4(SpearMoblinEntity* this) {
return (super->collisions & gUnk_080CC7D8[super->animationState >> 1]) != 0;
}
void sub_080288C0(SpearMoblinEntity* this) {
Entity* entity = super->child;
if ((entity != NULL) && (entity->contactFlags & CONTACT_TAKE_DAMAGE)) {
super->knockbackDirection = entity->knockbackDirection;
super->iframes = -entity->iframes;
super->knockbackSpeed = entity->knockbackSpeed;
super->knockbackDuration = entity->knockbackDuration;
entity->knockbackDuration = 0;
}
}
// clang-format off
void (*const SpearMoblin_Functions[])(SpearMoblinEntity*) = {
SpearMoblin_OnTick,
SpearMoblin_OnCollision,
(void (*)(SpearMoblinEntity*))GenericKnockback,
(void (*)(SpearMoblinEntity*))GenericDeath,
(void (*)(SpearMoblinEntity*))GenericConfused,
SpearMoblin_OnGrabbed,
};
void (*const gUnk_080CC7A8[])(SpearMoblinEntity*) = {
sub_08028314,
sub_08028378,
sub_08028420,
sub_08028488,
sub_08028528,
};
const u8 gUnk_080CC7BC[] = {
0x30, 0x60, 0x6C, 0x91,
};
const s8 gUnk_080CC7C0[] = {
0xF8, 0x0C,
0xF4, 0x08,
0x04, 0xFA,
0x06, 0xFC,
0x00, 0xFD,
0x01, 0x03,
0xFF, 0x02,
0x00, 0xFE,
};
const s8 gUnk_080CC7D0[] = {
0x08, 0x10,
0x08, 0x00,
0x10, 0x08,
0x10, 0x00,
};
const u16 gUnk_080CC7D8[] = {
0xE, 0xE000, 0xE0, 0xE00,
};
// clang-format on