tmc/src/enemy/tektite.c

225 lines
6.0 KiB
C

/**
* @file tektite.c
* @ingroup Enemies
*
* @brief Tektite enemy
*/
#include "collision.h"
#include "enemy.h"
#include "functions.h"
typedef struct {
/*0x00*/ Entity base;
/*0x68*/ u8 unused1[20];
/*0x7c*/ u8 unk_7c;
/*0x7d*/ u8 unused2[3];
/*0x80*/ u16 unk_80;
/*0x82*/ u16 unk_82;
} TektiteEntity;
static void sub_0802F45C(TektiteEntity* this);
static void Tektite_OnTick(TektiteEntity*);
static void Tektite_OnCollision(TektiteEntity*);
static void Tektite_OnConfused(TektiteEntity*);
static void Tektite_OnGrabbed(TektiteEntity*);
static void sub_0802F210(TektiteEntity*);
static void sub_0802F284(TektiteEntity*);
static void sub_0802F300(TektiteEntity*);
static void sub_0802F3F4(TektiteEntity*);
static void (*const Tektite_Functions[])(TektiteEntity*) = {
Tektite_OnTick,
Tektite_OnCollision,
(void (*)(TektiteEntity*))GenericKnockback,
(void (*)(TektiteEntity*))GenericDeath,
Tektite_OnConfused,
Tektite_OnGrabbed,
};
void Tektite(TektiteEntity* this) {
EnemyFunctionHandler(super, (EntityActionArray)Tektite_Functions);
EnemySetFXOffset(super, 0, 1, -0x10);
}
void Tektite_OnTick(TektiteEntity* this) {
static void (*const actionFuncs[])(TektiteEntity*) = {
sub_0802F210,
sub_0802F284,
sub_0802F300,
sub_0802F3F4,
};
actionFuncs[super->action](this);
}
static const u8 gUnk_080CDEF8[] = {
0x18,
0x28,
0x38,
0x48,
};
void Tektite_OnCollision(TektiteEntity* this) {
if (super->confusedTime != 0) {
EnemyCreateFX(super, FX_STARS);
}
EnemyFunctionHandlerAfterCollision(super, Tektite_Functions);
if ((super->contactFlags & CONTACT_NOW) != 0) {
switch (super->contactFlags & 0x3f) {
case 0x14:
super->action = 1;
super->subAction = 0;
if (super->type != 0) {
super->timer = 192;
} else {
super->timer = gUnk_080CDEF8[Random() & 3];
}
super->subtimer = 0;
this->unk_7c = 0;
if (super->z.HALF.HI != 0) {
super->zVelocity >>= 2;
} else {
super->zVelocity = 0;
}
InitializeAnimation(super, 0);
break;
case 0xe:
case 0x15:
super->health = 0;
break;
}
}
}
void Tektite_OnGrabbed(TektiteEntity* this) {
}
void Tektite_OnConfused(TektiteEntity* this) {
GenericConfused(super);
if (super->z.HALF.HI != 0) {
GravityUpdate(super, this->unk_80);
}
}
void sub_0802F210(TektiteEntity* this) {
sub_0804A720(super);
super->action = 1;
super->subAction = 0;
super->timer = gUnk_080CDEF8[Random() & 3];
super->timer += (Random() & 0x1f);
super->subtimer = 0;
this->unk_7c = 0;
this->unk_80 = super->type == 0 ? Q_8_8(24.0) : Q_8_8(40.0);
this->unk_82 = super->type == 0 ? (Q_16_16(2.5) >> 4) : (Q_16_16(3.0) >> 4);
InitializeAnimation(super, 0);
}
void sub_0802F284(TektiteEntity* this) {
if (super->timer > 0x60) {
UpdateAnimationVariableFrames(super, 2);
} else {
GetNextFrame(super);
}
if (super->timer != 0) {
super->timer--;
} else if (super->subtimer != 0) {
if (super->frame & ANIM_DONE) {
super->action = 2;
super->timer = 16;
super->subtimer = super->type;
super->zVelocity = this->unk_82 << 4;
sub_0802F45C(this);
InitializeAnimation(super, 2);
}
} else if (super->frame & ANIM_DONE) {
super->subtimer = 64;
InitializeAnimation(super, 1);
}
}
void sub_0802F300(TektiteEntity* this) {
s32 temp;
u32 rand;
GetNextFrame(super);
ProcessMovement0(super);
temp = super->z.HALF.HI;
rand = Random() & 0xf;
if (BounceUpdate(super, this->unk_80) == BOUNCE_INIT_NEXT) {
super->action = 3;
super->subAction = 0;
if (super->type != 0) {
rand = 0;
}
if (rand == 0) {
super->timer = 192;
} else {
super->timer = gUnk_080CDEF8[rand & 3] + rand;
}
super->subtimer = 0;
InitializeAnimation(super, 3);
return;
} else if (super->collisions != COL_NONE) {
sub_0800417E(super, super->collisions);
} else if ((GetActTileAtEntity(super) & 0xf0) == 0x50) { // ACT_TILE_240 and ACT_TILE_241?
super->direction = (super->direction + 0x10) & (0x3 | DirectionNorthWest);
}
if (--super->timer == 0) {
super->timer = 16;
if (super->subtimer != 0) {
super->subtimer--;
sub_0802F45C(this);
}
}
if ((super->subAction == 0) && (temp < super->z.HALF.HI)) {
InitializeAnimation(super, 4);
super->subAction = 1;
}
if (temp < -0xc) {
super->spriteRendering.b3 = 1;
super->spriteOrientation.flipY = 1;
} else {
super->spriteRendering.b3 = 2;
super->spriteOrientation.flipY = 2;
}
}
void sub_0802F3F4(TektiteEntity* this) {
GetNextFrame(super);
if (super->frame & ANIM_DONE) {
if ((this->unk_7c < 2) && ((super->type % 2) != 0)) {
super->action = 2;
super->timer = 16;
super->subtimer = super->type;
super->zVelocity = this->unk_82 << 4;
this->unk_7c++;
sub_0802F45C(this);
InitializeAnimation(super, 2);
} else {
super->action = 1;
this->unk_7c = 0;
InitializeAnimation(super, 0);
}
}
}
static void sub_0802F45C(TektiteEntity* this) {
u32 temp;
if (sub_08049FA0(super) == 0) {
super->direction = sub_08049EE4(super);
} else if (sub_08049FDC(super, 1) != 0) {
super->direction = sub_08049F84(super, 1);
} else {
temp = (Random() & 0xf) + 0x18;
super->direction = (temp + super->direction) & (0x3 | DirectionNorthWest);
}
}