mirror of
https://github.com/zeldaret/tmc
synced 2026-06-05 03:08:20 -04:00
514 lines
16 KiB
C
514 lines
16 KiB
C
/**
|
|
* @file vaatiBall.c
|
|
* @ingroup Enemies
|
|
*
|
|
* @brief Vaati Ball enemy
|
|
*/
|
|
|
|
#include "entity.h"
|
|
#include "enemy.h"
|
|
#include "player.h"
|
|
#include "object.h"
|
|
#include "functions.h"
|
|
|
|
typedef struct {
|
|
s8 h, v;
|
|
} PACKED PosOffset;
|
|
|
|
extern void (*const gUnk_080D1604[])(Entity*);
|
|
extern PosOffset gUnk_080D1620[4];
|
|
|
|
extern void sub_08044E74(Entity*, u32);
|
|
|
|
void VaatiBall(Entity* this) {
|
|
Entity* parent;
|
|
|
|
parent = this->parent;
|
|
if (this->action && this->action != 3) {
|
|
this->x.WORD += parent->x.WORD - *(int*)&parent->field_0x78;
|
|
this->y.WORD += parent->y.WORD - parent->field_0x7c.WORD;
|
|
}
|
|
|
|
gUnk_080D1604[this->action](this);
|
|
|
|
if (this->cutsceneBeh.HALF.LO) {
|
|
this->health = -1;
|
|
}
|
|
|
|
if (this->contactFlags & 0x80) {
|
|
if ((this->contactFlags & 0x3f) == 0 && this->action == 6) {
|
|
ModHealth(-2);
|
|
}
|
|
|
|
#ifdef EU
|
|
if (this->health < 0xfa) {
|
|
#else
|
|
if (this->health < 0xfd) {
|
|
#endif
|
|
this->spriteSettings.draw = 0;
|
|
COLLISION_OFF(this);
|
|
this->health = -1;
|
|
parent->field_0x80.HALF.LO--;
|
|
CreateDust(this);
|
|
SoundReq(SFX_1C3);
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_0804468C(Entity* this) {
|
|
PosOffset* off;
|
|
|
|
this->collisionLayer = 3;
|
|
this->spriteRendering.b3 = 2;
|
|
this->spritePriority.b0 = 5;
|
|
this->cutsceneBeh.HALF.LO = 0;
|
|
switch (this->type) {
|
|
case 0:
|
|
this->action = 1;
|
|
this->timer = 1;
|
|
this->direction = (this->field_0x78.HALF.HI * 8) & 0x1f;
|
|
this->field_0x78.HALF.LO = 0;
|
|
this->field_0x82.HALF.HI = 0;
|
|
this->spriteSettings.draw = 0;
|
|
off = &gUnk_080D1620[this->field_0x78.HALF.HI & 3];
|
|
PositionRelative(this->parent, this, Q_16_16(off->h), Q_16_16(off->v - 0x10));
|
|
this->z.HALF.HI = this->parent->z.HALF.HI;
|
|
InitAnimationForceUpdate(this, 0);
|
|
break;
|
|
case 1:
|
|
this->action = 3;
|
|
this->field_0x74.HALF.LO = 0;
|
|
this->field_0x82.HALF.HI = 1;
|
|
this->spriteSettings.draw = 1;
|
|
InitAnimationForceUpdate(this, 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void sub_0804474C(Entity* this) {
|
|
switch (this->parent->action) {
|
|
case 3:
|
|
this->action = 3;
|
|
this->field_0x74.HALF.LO = 0;
|
|
this->timer = 0;
|
|
break;
|
|
case 5:
|
|
this->action = 5;
|
|
this->field_0x74.HALF.LO = 0;
|
|
this->subtimer = 1;
|
|
break;
|
|
case 6:
|
|
this->action = 6;
|
|
this->field_0x74.HALF.LO = 0;
|
|
this->subtimer = 32;
|
|
break;
|
|
case 2:
|
|
this->action = 2;
|
|
this->field_0x74.HALF.LO = 0;
|
|
this->hitType = 0;
|
|
break;
|
|
}
|
|
|
|
if (this->action != 1) {
|
|
UpdateAnimationSingleFrame(this);
|
|
} else {
|
|
if (--this->timer == 0) {
|
|
this->timer = 2;
|
|
this->direction++;
|
|
this->direction &= 0x1f;
|
|
}
|
|
LinearMoveUpdate(this);
|
|
UpdateAnimationSingleFrame(this);
|
|
}
|
|
}
|
|
|
|
void sub_080447E0(Entity* this) {
|
|
Entity* vaati = this->parent;
|
|
|
|
if (vaati->action == 1) {
|
|
this->action = 1;
|
|
this->hitType = 43;
|
|
sub_08044E74(this, 0);
|
|
if (this->flags & ENT_COLLIDE)
|
|
this->spriteSettings.draw = 1;
|
|
} else {
|
|
this->field_0x76.HALF.HI++;
|
|
this->field_0x76.HALF.HI &= 7;
|
|
if (this->flags & ENT_COLLIDE) {
|
|
if (this->field_0x76.HALF.HI & 1) {
|
|
this->spriteSettings.draw = 1;
|
|
} else {
|
|
this->spriteSettings.draw = 0;
|
|
}
|
|
}
|
|
|
|
if (vaati->field_0x74.HALF.LO == 2) {
|
|
sub_08044E74(this, 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void sub_08044DEC(Entity*);
|
|
|
|
void sub_08044868(Entity* this) {
|
|
Entity* vaati = this->parent;
|
|
|
|
switch (vaati->field_0x74.HALF.LO) {
|
|
case 0xfe:
|
|
if (this->field_0x82.HALF.HI && this->field_0x74.HALF.LO == 2)
|
|
DeleteThisEntity();
|
|
break;
|
|
case 0xff:
|
|
if (this->field_0x82.HALF.HI) {
|
|
switch (this->field_0x74.HALF.LO) {
|
|
case 0:
|
|
if (this->frame & ANIM_DONE) {
|
|
this->field_0x74.HALF.LO = 1;
|
|
this->direction = sub_080045B4(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10);
|
|
this->speed = 0x180;
|
|
}
|
|
break;
|
|
case 1:
|
|
LinearMoveUpdate(this);
|
|
if (EntityWithinDistance(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10, 0xc)) {
|
|
this->field_0x74.HALF.LO++;
|
|
this->x.HALF.HI = vaati->x.HALF.HI;
|
|
this->y.HALF.HI = vaati->y.HALF.HI - 0x10;
|
|
vaati->timer++;
|
|
} else {
|
|
this->direction = sub_080045B4(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 1:
|
|
if (this->field_0x82.HALF.HI == 0) {
|
|
this->field_0x82.HALF.HI++;
|
|
this->spriteSettings.draw = 1;
|
|
}
|
|
sub_08044DEC(this);
|
|
if (*(u8*)&vaati->field_0x86 > 1) {
|
|
u8 draw = this->spriteSettings.draw;
|
|
if (draw == 1 && this->cutsceneBeh.HALF.LO == 0) {
|
|
vaati = CreateProjectileWithParent(this, V1_DARK_MAGIC_PROJECTILE, 0);
|
|
if (vaati) {
|
|
vaati->type2 = 1;
|
|
vaati->parent = this;
|
|
this->cutsceneBeh.HALF.LO = 1;
|
|
this->hitType = 0;
|
|
}
|
|
}
|
|
}
|
|
this->timer = 32;
|
|
break;
|
|
case 2:
|
|
if (this->timer)
|
|
if (--this->timer < 0x11)
|
|
LinearMoveUpdate(this);
|
|
break;
|
|
case 3: {
|
|
u8 draw;
|
|
|
|
sub_08044E74(this, 1);
|
|
draw = this->spriteSettings.draw;
|
|
if (draw == 1) {
|
|
COLLISION_ON(this);
|
|
} else {
|
|
COLLISION_OFF(this);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
UpdateAnimationSingleFrame(this);
|
|
}
|
|
|
|
void sub_080449F8(Entity* this) {
|
|
Entity* vaati = this->parent;
|
|
|
|
UpdateAnimationSingleFrame(this);
|
|
if (vaati->action == 1) {
|
|
sub_08044E74(this, 0);
|
|
return;
|
|
}
|
|
|
|
switch (vaati->field_0x74.HALF.LO) {
|
|
case 0:
|
|
LinearMoveUpdate(this);
|
|
if (--this->timer)
|
|
break;
|
|
|
|
if (this->field_0x78.HALF.LO == 0) {
|
|
this->field_0x78.HALF.LO++;
|
|
this->speed = 640;
|
|
}
|
|
|
|
this->timer = 4;
|
|
this->direction++;
|
|
this->direction &= 0x1f;
|
|
if (vaati->field_0x80.HALF.LO == 0)
|
|
vaati->field_0x74.HALF.LO = 1;
|
|
break;
|
|
case 1:
|
|
switch (this->timer) {
|
|
case 2:
|
|
if (vaati->field_0x80.HALF.LO == 0) {
|
|
this->subtimer = 0;
|
|
sub_08044E74(this, 0);
|
|
}
|
|
break;
|
|
case 1:
|
|
this->direction = (this->direction + 0x10) & 0x1f;
|
|
LinearMoveUpdate(this);
|
|
this->direction = (this->direction + 0x10) & 0x1f;
|
|
this->timer = 2;
|
|
break;
|
|
case 3:
|
|
LinearMoveUpdate(this);
|
|
this->timer = 2;
|
|
break;
|
|
case 4:
|
|
LinearMoveUpdate(this);
|
|
LinearMoveUpdate(this);
|
|
this->timer = 2;
|
|
break;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (this->field_0x74.HALF.LO == 0) {
|
|
u8 draw;
|
|
|
|
this->field_0x74.HALF.LO++;
|
|
draw = this->spriteSettings.draw;
|
|
if (draw) {
|
|
vaati = CreateProjectileWithParent(this, V1_EYE_LASER, 0);
|
|
if (vaati) {
|
|
vaati->y.HALF.HI += 4;
|
|
vaati->parent = this;
|
|
this->child = vaati;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
if (this->subtimer) {
|
|
this->subtimer = 0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void sub_08044B04(Entity* this) {
|
|
Entity* vaati = this->parent;
|
|
|
|
UpdateAnimationSingleFrame(this);
|
|
if (vaati->action == 1) {
|
|
sub_08044E74(this, 0);
|
|
this->timer = 32;
|
|
return;
|
|
}
|
|
|
|
switch (vaati->field_0x74.HALF.LO) {
|
|
case 0:
|
|
LinearMoveUpdate(this);
|
|
switch (this->field_0x74.HALF.LO) {
|
|
case 0:
|
|
if (--this->timer == 0) {
|
|
this->timer = this->field_0x78.HALF.LO ? 4 : 2;
|
|
this->direction++;
|
|
this->direction &= 0x1f;
|
|
}
|
|
if (--this->subtimer == 0) {
|
|
if (this->timer != 2) {
|
|
this->subtimer = 1;
|
|
} else {
|
|
if (++this->field_0x78.HALF.LO > 2) {
|
|
this->field_0x74.HALF.LO++;
|
|
this->field_0x78.HALF.LO = 1;
|
|
this->timer = 4;
|
|
this->subtimer = 0;
|
|
} else {
|
|
this->subtimer = 32;
|
|
}
|
|
|
|
this->speed = this->field_0x78.HALF.LO ? 640 : 1280;
|
|
}
|
|
}
|
|
break;
|
|
case 1:
|
|
if (--this->timer == 0) {
|
|
this->timer = 6;
|
|
this->direction = (this->direction + 1) & 0x1f;
|
|
if (++this->subtimer == 0x30) {
|
|
u32 direction = sub_080045B4(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10);
|
|
this->speed = 0;
|
|
this->direction = (direction + 16) & 0x1f;
|
|
this->timer = 16;
|
|
this->subtimer = 16;
|
|
this->field_0x74.HALF.LO++;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
if (this->subtimer == 0) {
|
|
switch (--this->timer) {
|
|
case 12:
|
|
this->speed = 1280;
|
|
break;
|
|
case 0:
|
|
this->field_0x74.HALF.LO++;
|
|
this->direction = sub_080045B4(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10);
|
|
this->speed = 0;
|
|
this->timer = 4;
|
|
this->subtimer = 16;
|
|
break;
|
|
case 4:
|
|
this->speed = 640;
|
|
break;
|
|
}
|
|
} else {
|
|
if (--this->subtimer == 0)
|
|
this->speed = 640;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (this->subtimer) {
|
|
if (--this->subtimer == 0)
|
|
this->speed = 640;
|
|
} else {
|
|
if (this->timer) {
|
|
if (--this->timer == 0) {
|
|
this->speed = 1280;
|
|
SoundReq(SFX_14F);
|
|
}
|
|
}
|
|
if (this->field_0x78.HALF.HI == 3)
|
|
if (EntityWithinDistance(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10, 0xc))
|
|
vaati->timer++;
|
|
this->direction = sub_080045B4(this, vaati->x.HALF.HI, vaati->y.HALF.HI - 0x10);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 1:
|
|
switch (this->field_0x74.HALF.LO) {
|
|
case 3:
|
|
this->field_0x74.HALF.LO = 1;
|
|
this->timer = 80;
|
|
COLLISION_OFF(this);
|
|
PositionRelative(vaati, this, 0, Q_16_16(-16.0));
|
|
if (this->subtimer)
|
|
this->spriteSettings.draw = 0;
|
|
break;
|
|
case 1:
|
|
if (--this->timer == 0) {
|
|
this->field_0x74.HALF.LO = 0;
|
|
this->timer = 32;
|
|
this->subtimer = 4;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 2:
|
|
/* ... */
|
|
break;
|
|
case 3:
|
|
switch (this->field_0x74.HALF.LO) {
|
|
case 0:
|
|
if (this->subtimer) {
|
|
if (--this->subtimer == 0) {
|
|
sub_08044DEC(this);
|
|
this->field_0x74.HALF.LO = 1;
|
|
this->timer = 16;
|
|
}
|
|
}
|
|
break;
|
|
case 1:
|
|
LinearMoveUpdate(this);
|
|
if (--this->timer == 0)
|
|
this->field_0x74.HALF.LO++;
|
|
break;
|
|
case 2: {
|
|
u8 draw;
|
|
|
|
sub_08044E74(this, 1);
|
|
draw = this->spriteSettings.draw;
|
|
if (draw == 1) {
|
|
COLLISION_ON(this);
|
|
} else {
|
|
COLLISION_OFF(this);
|
|
}
|
|
vaati->timer++;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
extern u8 gUnk_080D1628[4][4];
|
|
|
|
void sub_08044DEC(Entity* this) {
|
|
u32 off;
|
|
|
|
if (this->parent->field_0x80.HALF.LO > this->field_0x78.HALF.HI) {
|
|
this->spriteSettings.draw = 1;
|
|
this->health = -1;
|
|
} else {
|
|
this->spriteSettings.draw = 0;
|
|
}
|
|
COLLISION_OFF(this);
|
|
this->field_0x78.HALF.LO = 0;
|
|
this->speed = 0x300;
|
|
off = this->parent->field_0x80.HALF.LO - 1;
|
|
this->direction = gUnk_080D1628[off][this->field_0x78.HALF.HI];
|
|
PositionRelative(this->parent, this, 0, Q_16_16(-16.0));
|
|
}
|
|
|
|
void sub_08044E74(Entity* this, u32 state) {
|
|
this->action = 1;
|
|
this->field_0x74.HALF.LO = 0;
|
|
|
|
switch (state) {
|
|
case 2:
|
|
this->action = 2;
|
|
this->direction += 0x18;
|
|
this->direction &= 0x1f;
|
|
PositionRelative(this->parent, this, 0, Q_16_16(-16.0));
|
|
this->speed = 12288;
|
|
LinearMoveUpdate(this);
|
|
this->direction += 0x8;
|
|
this->direction &= 0x1f;
|
|
this->speed = 1280;
|
|
LinearMoveUpdate(this);
|
|
break;
|
|
case 1:
|
|
this->direction = (this->direction + 8) & 0x1f;
|
|
break;
|
|
case 0:
|
|
if (this->field_0x78.HALF.LO) {
|
|
switch (this->timer) {
|
|
case 3 ... 4:
|
|
do {
|
|
LinearMoveUpdate(this);
|
|
} while (this->timer-- != 3);
|
|
break;
|
|
case 1:
|
|
this->direction = (this->direction + 0x10) & 0x1f;
|
|
LinearMoveUpdate(this);
|
|
this->direction = (this->direction + 0x10) & 0x1f;
|
|
break;
|
|
}
|
|
} else {
|
|
if (this->timer == 2) {
|
|
LinearMoveUpdate(this);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
this->timer = 1;
|
|
this->field_0x78.HALF.LO = 0;
|
|
this->speed = Q_8_8(5);
|
|
}
|