mirror of
https://github.com/zeldaret/tmc
synced 2026-05-27 16:14:05 -04:00
417 lines
10 KiB
C
417 lines
10 KiB
C
/**
|
|
* @file bowMoblin.c
|
|
* @ingroup Enemies
|
|
*
|
|
* @brief Bow Moblin enemy
|
|
*/
|
|
#include "enemy.h"
|
|
#include "entity.h"
|
|
#include "functions.h"
|
|
|
|
typedef struct {
|
|
Entity base;
|
|
u8 filler[0x12];
|
|
u8 unk_0x7a;
|
|
u8 unk_0x7b;
|
|
u8 filter[0x4];
|
|
u8 unk_0x80;
|
|
u8 unk_0x81;
|
|
u8 unk_0x82;
|
|
u8 unk_0x83;
|
|
} BowMoblinEntity;
|
|
|
|
void sub_0803C5F0(BowMoblinEntity*);
|
|
void sub_0803C690(BowMoblinEntity*);
|
|
void sub_0803C4B0(BowMoblinEntity*);
|
|
void sub_0803C5C4(BowMoblinEntity*);
|
|
void sub_0803C624(BowMoblinEntity*);
|
|
void sub_0803C6DC(BowMoblinEntity*);
|
|
void sub_0803C714(BowMoblinEntity*);
|
|
void sub_0803C634(BowMoblinEntity*);
|
|
bool32 sub_0803C6F8(BowMoblinEntity*);
|
|
bool32 sub_0803C568(BowMoblinEntity*);
|
|
void sub_0803C664(BowMoblinEntity*);
|
|
|
|
void (*const BowMoblin_Functions[])(Entity*);
|
|
void (*const gUnk_080CFF90[])(BowMoblinEntity*);
|
|
|
|
const s8 gUnk_080CFFA4[8];
|
|
const s8 gUnk_080CFFAC[16];
|
|
const u16 gUnk_080CFFBC[4];
|
|
const s8 gUnk_080CFFC4[8];
|
|
|
|
void BowMoblin(Entity* this) {
|
|
EnemyFunctionHandler(this, BowMoblin_Functions);
|
|
EnemySetFXOffset(this, 0, 1, -0x18);
|
|
}
|
|
|
|
void BowMoblin_OnTick(BowMoblinEntity* this) {
|
|
gUnk_080CFF90[super->action](this);
|
|
}
|
|
|
|
void BowMoblin_OnCollision(BowMoblinEntity* this) {
|
|
Entity* pEVar1;
|
|
|
|
if (super->confusedTime != 0) {
|
|
EnemyCreateFX(super, FX_STARS);
|
|
}
|
|
EnemyFunctionHandlerAfterCollision(super, (EntityActionArray)BowMoblin_Functions);
|
|
if ((super->contactFlags & 0x80) != 0) {
|
|
sub_0803C5F0(this);
|
|
pEVar1 = super->child;
|
|
if (pEVar1 != NULL) {
|
|
pEVar1->subtimer++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void BowMoblin_OnGrabbed(BowMoblinEntity* this) {
|
|
}
|
|
|
|
void sub_0803C1E0(BowMoblinEntity* this) {
|
|
sub_0804A720(super);
|
|
|
|
super->action = 1;
|
|
this->unk_0x7b = 0;
|
|
this->unk_0x80 = 0;
|
|
this->unk_0x83 = 0;
|
|
this->unk_0x81 = 0;
|
|
this->unk_0x7a = 0;
|
|
this->unk_0x82 = 1;
|
|
|
|
if (super->timer != 0) {
|
|
super->animationState = super->type2 << 1;
|
|
super->timer = 30;
|
|
super->speed = 0x80;
|
|
super->direction = super->type2 << 3;
|
|
sub_0803C690(this);
|
|
} else {
|
|
super->animationState = 0x10;
|
|
sub_0803C4B0(this);
|
|
}
|
|
}
|
|
|
|
void sub_0803C234(BowMoblinEntity* this) {
|
|
u8 mask;
|
|
if (this->unk_0x81) {
|
|
this->unk_0x81--;
|
|
}
|
|
mask = 0xff;
|
|
if (((--super->timer) & mask) == 0) {
|
|
u8 tmp = ++this->unk_0x80;
|
|
|
|
if ((tmp) > 0xf) {
|
|
sub_0803C5C4(this);
|
|
} else if (((this->unk_0x80 & 0x3) == 0) && (Random() & 0x10)) {
|
|
sub_0803C624(this);
|
|
} else {
|
|
sub_0803C4B0(this);
|
|
}
|
|
|
|
} else if (sub_0803C6F8(this)) {
|
|
sub_0800417E(super, super->collisions);
|
|
super->animationState = ((super->direction + 4) & 0x18) >> 2;
|
|
this->unk_0x83++;
|
|
sub_0803C690(this);
|
|
} else if (sub_0803C568(this)) {
|
|
sub_0803C5F0(this);
|
|
}
|
|
|
|
sub_0803C6DC(this);
|
|
}
|
|
|
|
void sub_0803C2DC(BowMoblinEntity* this) {
|
|
u32 timer = --super->timer;
|
|
if (timer == 0) {
|
|
super->action = 3;
|
|
this->unk_0x82 = timer;
|
|
this->unk_0x80 = timer;
|
|
super->animationState = 0x10;
|
|
sub_0803C4B0(this);
|
|
} else if (sub_0803C568(this)) {
|
|
this->unk_0x7b |= 0x1;
|
|
}
|
|
|
|
if (super->subtimer > 11) {
|
|
if (this->unk_0x7b != 0) {
|
|
sub_0803C5F0(this);
|
|
}
|
|
} else {
|
|
super->subtimer++;
|
|
}
|
|
|
|
sub_0803C6DC(this);
|
|
}
|
|
|
|
void sub_0803C344(BowMoblinEntity* this) {
|
|
if (--super->timer == 0) {
|
|
switch (this->unk_0x82) {
|
|
case 3: {
|
|
super->action = 4;
|
|
super->speed = 0x80;
|
|
super->direction = sub_08049F84(super, 1);
|
|
break;
|
|
}
|
|
case 5: {
|
|
super->action = 4;
|
|
super->speed = 0x80;
|
|
break;
|
|
}
|
|
case 2: {
|
|
u32 tmp;
|
|
super->action = 2;
|
|
super->speed = 0;
|
|
tmp = Random() & 0x7;
|
|
super->timer = 3 * tmp + 64;
|
|
break;
|
|
}
|
|
case 4: {
|
|
super->direction = (super->direction + 0x10) & 0x18;
|
|
}
|
|
case 0:
|
|
case 1:
|
|
default: {
|
|
u32 tmp;
|
|
super->action = 1;
|
|
this->unk_0x82 = 1;
|
|
super->speed = 0x80;
|
|
tmp = (Random() & 0x7);
|
|
super->timer = 3 * tmp + 34;
|
|
break;
|
|
}
|
|
}
|
|
|
|
super->subtimer = 0;
|
|
super->animationState = ((super->direction + 4) & 0x18) >> 2;
|
|
sub_0803C690(this);
|
|
}
|
|
sub_0803C6DC(this);
|
|
}
|
|
|
|
void sub_0803C400(BowMoblinEntity* this) {
|
|
if (super->subtimer) {
|
|
u8 mask;
|
|
super->subtimer--;
|
|
mask = 0xff;
|
|
if ((super->subtimer & mask) == 0) {
|
|
if (this->unk_0x82 == 3) {
|
|
this->unk_0x7a++;
|
|
if ((this->unk_0x7a & mask) <= 2) {
|
|
if (Random() & 0xc0) {
|
|
super->timer = 0;
|
|
sub_0803C690(this);
|
|
sub_0803C6DC(this);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
sub_0803C634(this);
|
|
}
|
|
} else {
|
|
Entity* projectile;
|
|
|
|
switch (++super->timer) {
|
|
case 1:
|
|
super->direction = super->animationState << 2;
|
|
projectile = EnemyCreateProjectile(super, ARROW_PROJECTILE, super->animationState >> 1);
|
|
if (projectile) {
|
|
super->child = projectile;
|
|
projectile->direction = (super->direction + 4) & 0x18;
|
|
projectile->parent = super;
|
|
}
|
|
break;
|
|
case 24:
|
|
super->timer = 0;
|
|
super->subtimer = 32;
|
|
break;
|
|
}
|
|
|
|
sub_0803C6DC(this);
|
|
if (super->child != NULL) {
|
|
sub_0803C714(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_0803C4B0(BowMoblinEntity* this) {
|
|
u32 dir;
|
|
super->subtimer = 0;
|
|
if (this->unk_0x82 == 1) {
|
|
super->timer = gUnk_080CFFA4[Random() & 7];
|
|
super->speed = 0x80;
|
|
if (sub_08049FA0(super)) {
|
|
dir = Random();
|
|
dir &= 6;
|
|
super->direction = dir << 2;
|
|
} else {
|
|
dir = sub_08049EE4(super);
|
|
if (this->unk_0x83 == 0) {
|
|
dir += gUnk_080CFFAC[Random() & 0xf];
|
|
} else {
|
|
dir += gUnk_080CFFAC[Random() & 0x7];
|
|
super->timer += 16;
|
|
this->unk_0x83--;
|
|
}
|
|
dir = (super->direction = (dir + 4) & 0x18) >> 2;
|
|
}
|
|
} else {
|
|
super->timer = 12;
|
|
super->speed = super->subtimer;
|
|
dir = super->direction >> 2;
|
|
}
|
|
if (dir != super->animationState) {
|
|
super->animationState = dir;
|
|
sub_0803C690(this);
|
|
}
|
|
}
|
|
|
|
bool32 sub_0803C568(BowMoblinEntity* this) {
|
|
if (this->unk_0x81 == 0) {
|
|
Entity* entity = sub_08049DF4(1);
|
|
if (entity != NULL) {
|
|
if (this->unk_0x82 == 2) {
|
|
if (sub_0806FC80(super, entity, 0x30)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (sub_0806FC80(super, entity, 0x40)) {
|
|
u32 direction = (GetFacingDirection(super, entity) + 4) & 0x18;
|
|
direction = direction >> 2;
|
|
if (direction == super->animationState) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void sub_0803C5C4(BowMoblinEntity* this) {
|
|
u32 state = ((super->direction + 4) & 0x18) >> 2;
|
|
super->animationState = state;
|
|
super->direction = state << 2;
|
|
this->unk_0x83 >>= 1;
|
|
sub_0803C664(this);
|
|
this->unk_0x82 = 2;
|
|
}
|
|
|
|
void sub_0803C5F0(BowMoblinEntity* this) {
|
|
super->direction = sub_08049F84(super, 1);
|
|
super->animationState = ((super->direction + 4) & 0x18) >> 2;
|
|
this->unk_0x83 = 0;
|
|
this->unk_0x7a = 0;
|
|
sub_0803C664(this);
|
|
this->unk_0x82 = 3;
|
|
}
|
|
|
|
void sub_0803C624(BowMoblinEntity* this) {
|
|
sub_0803C664(this);
|
|
this->unk_0x82 = 5;
|
|
}
|
|
|
|
void sub_0803C634(BowMoblinEntity* this) {
|
|
super->animationState = ((super->direction + 4) & 0x18) >> 2;
|
|
super->direction = super->animationState << 2;
|
|
this->unk_0x83 = 0;
|
|
sub_0803C664(this);
|
|
super->timer *= 2;
|
|
this->unk_0x82 = 4;
|
|
}
|
|
|
|
void sub_0803C664(BowMoblinEntity* this) {
|
|
super->action = 3;
|
|
super->timer = 32;
|
|
super->subtimer = 0;
|
|
this->unk_0x80 = 0;
|
|
this->unk_0x7b = 0;
|
|
super->speed = 0;
|
|
this->unk_0x82 = 0;
|
|
sub_0803C690(this);
|
|
}
|
|
|
|
void sub_0803C690(BowMoblinEntity* this) {
|
|
u32 tmp = super->animationState >> 1;
|
|
switch (this->unk_0x82) {
|
|
case 1:
|
|
case 4: {
|
|
tmp += 0x4;
|
|
break;
|
|
}
|
|
case 3:
|
|
case 5: {
|
|
tmp += 0x8;
|
|
break;
|
|
}
|
|
case 2: {
|
|
tmp += 0xc;
|
|
break;
|
|
}
|
|
case 0: {
|
|
break;
|
|
}
|
|
}
|
|
|
|
InitializeAnimation(super, tmp);
|
|
}
|
|
|
|
void sub_0803C6DC(BowMoblinEntity* this) {
|
|
u8 tmp = this->unk_0x82;
|
|
if (tmp == 0) {
|
|
super->speed = tmp;
|
|
}
|
|
|
|
ProcessMovement0(super);
|
|
GetNextFrame(super);
|
|
}
|
|
|
|
bool32 sub_0803C6F8(BowMoblinEntity* this) {
|
|
return (super->collisions & gUnk_080CFFBC[(super->animationState ^ 1) / 2]) != 0;
|
|
}
|
|
|
|
void sub_0803C714(BowMoblinEntity* this) {
|
|
Entity* child = super->child;
|
|
const s8* tmp;
|
|
u32 offsetX;
|
|
u32 offsetY;
|
|
tmp = &gUnk_080CFFC4[super->animationState];
|
|
// TODO fix array access
|
|
offsetX = tmp[0] << 0x10;
|
|
offsetY = tmp[1] << 0x10;
|
|
|
|
PositionRelative(super, child, offsetX, offsetY);
|
|
}
|
|
|
|
void (*const BowMoblin_Functions[])(Entity*) = {
|
|
(EntityActionPtr)BowMoblin_OnTick,
|
|
(EntityActionPtr)BowMoblin_OnCollision,
|
|
GenericKnockback,
|
|
GenericDeath,
|
|
GenericConfused,
|
|
(EntityActionPtr)BowMoblin_OnGrabbed,
|
|
};
|
|
|
|
void (*const gUnk_080CFF90[])(BowMoblinEntity*) = {
|
|
sub_0803C1E0, sub_0803C234, sub_0803C2DC, sub_0803C344, sub_0803C400,
|
|
};
|
|
|
|
const s8 gUnk_080CFFA4[8] = {
|
|
24, 32, 48, 64, 96, 108, 120, 145,
|
|
};
|
|
|
|
const s8 gUnk_080CFFAC[16] = {
|
|
0xf8, 0xc, 0xf4, 0x8, 0x4, 0xfa, 0x6, 0xfc, 0x0, 0xfd, 0x1, 0x3, 0xff, 0x2, 0x0, 0xfe,
|
|
};
|
|
|
|
const u16 gUnk_080CFFBC[4] = {
|
|
0xe,
|
|
0xe000,
|
|
0xe0,
|
|
0xe00,
|
|
};
|
|
|
|
const s8 gUnk_080CFFC4[8] = {
|
|
-5, -20, 15, -12, 4, -4, -15, -12,
|
|
};
|