mirror of
https://github.com/zeldaret/tmc
synced 2026-07-11 15:28:41 -04:00
153 lines
4.1 KiB
C
153 lines
4.1 KiB
C
/**
|
|
* @file fireballGuy.c
|
|
* @ingroup Enemies
|
|
*
|
|
* @brief Fireball Guy enemy
|
|
*/
|
|
#include "enemy.h"
|
|
#include "sound.h"
|
|
#include "effects.h"
|
|
#include "player.h"
|
|
#include "physics.h"
|
|
#include "asm.h"
|
|
|
|
typedef struct {
|
|
/*0x00*/ Entity base;
|
|
/*0x68*/ u8 unused1[28];
|
|
/*0x84*/ u8 unk_84;
|
|
} FireballGuyEntity;
|
|
|
|
typedef struct {
|
|
s8 h, v;
|
|
} PACKED PosOffset;
|
|
|
|
extern void sub_08045524(FireballGuyEntity*);
|
|
void sub_08045178(Entity*, Entity*, int, int);
|
|
void FireballGuy_OnTick(FireballGuyEntity*);
|
|
void FireballGuy_OnCollision(FireballGuyEntity*);
|
|
void FireballGuy_OnGrabbed(FireballGuyEntity*);
|
|
void FireballGuy_Init(FireballGuyEntity*);
|
|
void FireballGuy_Action1(FireballGuyEntity*);
|
|
void FireballGuy_Action2(FireballGuyEntity*);
|
|
|
|
static void (*const FireballGuy_Functions[])(FireballGuyEntity*) = {
|
|
FireballGuy_OnTick,
|
|
FireballGuy_OnCollision,
|
|
(void (*)(FireballGuyEntity*))GenericKnockback,
|
|
(void (*)(FireballGuyEntity*))GenericDeath,
|
|
(void (*)(FireballGuyEntity*))GenericConfused,
|
|
FireballGuy_OnGrabbed,
|
|
};
|
|
|
|
void FireballGuy(FireballGuyEntity* this) {
|
|
EnemyFunctionHandler(super, (EntityActionArray)FireballGuy_Functions);
|
|
}
|
|
|
|
void FireballGuy_OnTick(FireballGuyEntity* this) {
|
|
static void (*const FireballGuy_Actions[])(FireballGuyEntity*) = {
|
|
FireballGuy_Init,
|
|
FireballGuy_Action1,
|
|
FireballGuy_Action2,
|
|
};
|
|
FireballGuy_Actions[super->action](this);
|
|
}
|
|
|
|
void FireballGuy_OnCollision(FireballGuyEntity* this) {
|
|
if (super->health && this->unk_84 != super->health) {
|
|
super->action = 2;
|
|
} else {
|
|
EnemyFunctionHandlerAfterCollision(super, FireballGuy_Functions);
|
|
}
|
|
}
|
|
|
|
void FireballGuy_OnGrabbed(FireballGuyEntity* this) {
|
|
}
|
|
|
|
void FireballGuy_Init(FireballGuyEntity* this) {
|
|
super->action = 1;
|
|
super->timer = 0;
|
|
super->spriteSettings.draw = 1;
|
|
super->speed = 0x80;
|
|
this->unk_84 = super->health;
|
|
super->collisionFlags |= 0x10;
|
|
sub_0804A720(super);
|
|
InitializeAnimation(super, 0);
|
|
sub_08045524(this);
|
|
}
|
|
|
|
void FireballGuy_Action1(FireballGuyEntity* this) {
|
|
ProcessMovement2(super);
|
|
GetNextFrame(super);
|
|
if (GravityUpdate(super, Q_8_8(24.0)) == 0)
|
|
sub_08045524(this);
|
|
}
|
|
|
|
/* Split FireballGuy into new ones */
|
|
void FireballGuy_Action2(FireballGuyEntity* this) {
|
|
// Entity count per form
|
|
static const u8 typeEntityCount[4] = { 2, 3, 4, 5 };
|
|
static const PosOffset gUnk_080D1810[4] = { { 6, 0 }, { -6, 0 }, { 0, 6 }, { 0, -6 } };
|
|
Entity* entities[4];
|
|
Entity* entity;
|
|
s32 count, i;
|
|
const PosOffset* off;
|
|
u32 tmp;
|
|
|
|
/* Can we create enough new entities? */
|
|
count = typeEntityCount[super->type];
|
|
if (MAX_ENTITIES - count <= gEntCount)
|
|
return;
|
|
|
|
/* Create 2-5 new MiniFireballGuy */
|
|
for (i = 0; i < count; i++)
|
|
entities[i] = CreateEnemy(MINI_FIREBALL_GUY, super->type);
|
|
|
|
off = gUnk_080D1810;
|
|
for (i = 0; i < count; i++) {
|
|
entity = entities[i];
|
|
entity->child = entities[(i + 1) % count];
|
|
entity->parent = entities[(i + count - 1) % count];
|
|
tmp = 0;
|
|
entity->type2 = 1;
|
|
entity->z.HALF.HI = tmp;
|
|
entity->iframes = -0x10;
|
|
|
|
/* Set MiniFireballGuy offset relative to killed slime. */
|
|
sub_08045178(super, entity, off->h, off->v);
|
|
off++;
|
|
}
|
|
|
|
entity = CreateFx(super, FX_DEATH, 0);
|
|
if (entity != NULL)
|
|
CopyPosition(super, entity);
|
|
|
|
DeleteEntity(super);
|
|
}
|
|
|
|
u32 sub_0804A024(Entity*, u32, u32);
|
|
|
|
void sub_08045524(FireballGuyEntity* this) {
|
|
u32 tmp, tmp1, tmp2;
|
|
|
|
super->zVelocity = Q_16_16(1.75);
|
|
tmp = sub_0804A024(super, 1, 8);
|
|
if (tmp != DIR_NONE && (Random() & 3) == 0) {
|
|
super->timer = Random() & 3;
|
|
super->direction = DirectionRound(tmp);
|
|
} else {
|
|
if (super->timer != 0) {
|
|
super->timer--;
|
|
return;
|
|
}
|
|
super->timer = Random() & 3;
|
|
if (sub_08049FA0(super) == 0 && (Random() & 3)) {
|
|
tmp1 = sub_08049EE4(super);
|
|
tmp2 = Random() & 8;
|
|
tmp2 += 0xfc;
|
|
super->direction = DirectionRound(tmp1 + tmp2);
|
|
} else {
|
|
super->direction = DirectionRound(Random());
|
|
}
|
|
}
|
|
}
|