tmc/src/enemy/wizzrobeWind.c

331 lines
10 KiB
C

/**
* @file wizzrobeWind.c
* @ingroup Enemies
*
* @brief Wizzrobe Wind enemy
*/
#define NENT_DEPRECATED
#include "global.h"
#include "collision.h"
#include "enemy.h"
#include "enemy/wizzrobe.h"
#include "functions.h"
#include "object.h"
extern void (*const WizzrobeWind_Functions[])(WizzrobeEntity*);
extern void (*const WizzrobeWind_Actions[])(WizzrobeEntity*);
void sub_0802F888(WizzrobeEntity*);
void sub_0802FA48(WizzrobeEntity*);
bool32 sub_0802FA88(WizzrobeEntity*);
void sub_0802F9C8(WizzrobeEntity*);
void sub_0802F8E4(WizzrobeEntity*);
void WizzrobeWind(WizzrobeEntity* this) {
WizzrobeWind_Functions[GetNextFunction(super)](this);
SetChildOffset(super, 0, 1, -0x10);
}
void WizzrobeWind_OnTick(WizzrobeEntity* this) {
WizzrobeWind_Actions[super->action](this);
}
void WizzrobeWind_OnCollision(WizzrobeEntity* this) {
if (super->confusedTime != 0) {
Create0x68FX(super, FX_STARS);
}
EnemyFunctionHandlerAfterCollision(super, WizzrobeWind_Functions);
if (super->contactFlags == 0x87) {
Entity* obj = CreateObject(FLAME, 3, 0);
if (obj != NULL) {
obj->spritePriority.b0 = 3;
obj->spriteOffsetY = -4;
obj->parent = super;
}
}
if (super->health == 0) {
SetMetaTile(this->tileIndex, this->tilePosition, super->collisionLayer);
}
}
void WizzrobeWind_Init(WizzrobeEntity* this) {
Entity* projectile;
if (super->type2 != 0) {
super->action = 3;
super->speed = 0xc0;
super->flags |= 0x80;
this->targetIndex = 0;
super->child = (Entity*)GetCurrentRoomProperty(super->timer);
sub_0802FA48(this);
sub_0802FA88(this);
} else {
sub_0804A720(super);
super->action = 1;
this->timer2 = 0xff;
this->timer1 = 0x28;
super->timer = 40;
super->subtimer = 96;
sub_0802F888(this);
}
projectile = CreateProjectileWithParent(super, WIND_PROJECTILE, 0);
if (projectile != NULL) {
super->parent = projectile;
projectile->parent = super;
projectile->direction = super->direction;
}
InitializeAnimation(super, super->direction >> 3);
}
void WizzrobeWind_Action1(WizzrobeEntity* this) {
u8 tmp;
Entity* parent;
switch (this->timer2) {
case 0xff:
if (--super->subtimer == 0) {
this->timer2 = 0;
}
break;
case 0:
if (--super->timer == 0) {
this->timer2++;
super->timer = 16;
super->flags |= 0x80;
}
break;
case 1:
if (--super->timer == 0) {
super->action = 2;
this->timer2 = 0;
super->timer = 40;
tmp = super->direction >> 3;
parent = super->parent;
parent->timer = 1;
parent->spriteSettings.draw = 1;
InitializeAnimation(super, tmp | 4);
}
break;
}
sub_0802F9C8(this);
}
void WizzrobeWind_Action2(WizzrobeEntity* this) {
switch (this->timer2) {
case 0:
switch (--super->timer) {
case 0:
this->timer2++;
super->timer = 56;
super->subtimer = 0;
super->parent->spriteSettings.draw = 0;
break;
case 8:
if (EntityInRectRadius(super, &gPlayerEntity, 0xa0, 0xa0) && CheckOnScreen(super)) {
Entity* projectile = CreateProjectileWithParent(super, WIND_PROJECTILE, 1);
if (projectile != NULL) {
projectile->direction = super->direction & 0x18;
}
}
break;
}
break;
case 1:
if (--super->timer == 0) {
this->timer2++;
this->timer1 = 0x28;
super->timer = 40;
super->subtimer = 0;
super->flags &= ~0x80;
EnqueueSFX(SFX_156);
SetMetaTile(this->tileIndex, this->tilePosition, super->collisionLayer);
InitializeAnimation(super, super->direction >> 3);
}
break;
case 2:
if (--super->timer == 0) {
this->timer2++;
super->timer = (Random() & 0x3f) + 32;
super->spriteSettings.draw = 0;
}
break;
case 3:
if (--super->timer == 0) {
super->action = 1;
this->timer2 = 0;
this->timer1 = 0x28;
super->timer = 40;
EnqueueSFX(SFX_156);
sub_0802F8E4(this);
InitializeAnimation(super, super->direction >> 3);
}
break;
}
sub_0802F9C8(this);
}
void WizzrobeWind_Action3(WizzrobeEntity* this) {
Entity* parent;
sub_0802FA88(this);
sub_0802F9C8(this);
parent = super->parent;
if (this->timer1 == 0) {
switch (this->timer2) {
case 0:
this->timer2 = 1;
super->timer = 64;
break;
case 1:
if (--super->timer != 0) {
return;
}
this->timer2++;
super->timer = 40;
parent->timer = 1;
parent->spriteSettings.draw = 1;
InitializeAnimation(super, super->animationState >> 1 | 4);
break;
case 2:
if (--super->timer == 0) {
this->timer2++;
super->timer = (Random() & 0x1f) + 48;
parent->spriteSettings.draw = 0;
InitializeAnimation(super, super->animationState >> 1);
} else if (super->timer == 8) {
parent = CreateProjectileWithParent(super, WIND_PROJECTILE, 1);
if (parent != NULL) {
parent->direction = super->direction & 0x18;
}
}
}
} else {
if (this->timer2 != 0) {
this->timer2 = 0;
parent->spriteSettings.draw = 0;
}
}
}
void sub_0802F888(WizzrobeEntity* this) {
super->direction = (sub_08049F84(super, 3) + 4) & 0x18;
this->tilePosition = COORD_TO_TILE(super);
this->tileIndex = GetMetaTileIndex(this->tilePosition, super->collisionLayer);
SetMetaTile(0x4071, this->tilePosition, super->collisionLayer);
}
void sub_0802F8E4(WizzrobeEntity* this) {
u16 uVar1;
s32 iVar4;
u32 uVar6;
u32 uVar7;
u32 uVar8;
bool32 loopCondition;
u32 rand;
if (super->type2 == 0) {
loopCondition = TRUE;
do {
rand = Random();
uVar1 = this->unk_70;
iVar4 = ((s32)rand & 0x7ff0) % (this->unk_6e << 3);
uVar8 = (uVar1 + iVar4) | 8;
rand >>= 0x10;
uVar1 = this->unk_72;
iVar4 = ((s32)(rand)&0x7ff0) % (this->unk_6f << 3);
uVar7 = (uVar1 + iVar4) | 8;
uVar6 = TILE(uVar8, uVar7);
if ((GetCollisionDataAtMetaTilePos(uVar6, super->collisionLayer) == 0) &&
(GetMetaTileIndex(uVar6, super->collisionLayer) != 0x4071)) {
super->x.HALF.HI = (s16)uVar8;
super->y.HALF.HI = (s16)uVar7;
if (sub_08049FA0(super) != 0) {
loopCondition = FALSE;
}
}
} while (loopCondition);
sub_0802F888(this);
}
}
void sub_0802F9C8(WizzrobeEntity* this) {
if (super->subtimer == 0) {
if (this->timer1 != 0) {
if ((--this->timer1 & 1) != 0) {
super->spriteSettings.draw = 0;
} else {
super->spriteSettings.draw = 1;
}
if ((super->type2 != 0) && (LinearMoveUpdate(super), this->timer1 == 0)) {
super->flags |= 0x80;
}
} else {
if (super->type2 != 0) {
ProcessMovement0(super);
if (super->collisions != COL_NONE) {
super->flags &= ~0x80;
this->timer1 = 0x28;
}
}
}
GetNextFrame(super);
}
}
void sub_0802FA48(WizzrobeEntity* this) {
u16* target;
u16* child;
child = (u16*)super->child;
target = &child[this->targetIndex * 2];
if (target[0] == 0xffff) {
this->targetIndex = 0;
target = child;
}
this->targetX = gRoomControls.origin_x + target[0];
this->targetY = gRoomControls.origin_y + target[1];
}
bool32 sub_0802FA88(WizzrobeEntity* this) {
u32 direction;
bool32 result = FALSE;
if (EntityWithinDistance(super, this->targetX, this->targetY, 2)) {
this->targetIndex++;
sub_0802FA48(this);
direction = CalculateDirectionTo(super->x.HALF.HI, super->y.HALF.HI, this->targetX, this->targetY);
super->direction = direction;
super->animationState = ((direction + 4) & 0x18) >> 2;
if (((super->parent)->spriteSettings.draw & 3) != 0) {
InitializeAnimation(super, direction >> 3 | 4);
} else {
InitializeAnimation(super, direction >> 3);
}
result = TRUE;
} else {
direction = CalculateDirectionTo(super->x.HALF.HI, super->y.HALF.HI, this->targetX, this->targetY);
sub_08004596(super, direction);
direction = ((super->direction + 4) & 0x18) >> 2;
if (direction != super->animationState) {
super->animationState = direction;
InitializeAnimation(super, direction >> 1);
}
}
return result;
}
void (*const WizzrobeWind_Functions[])(WizzrobeEntity*) = {
WizzrobeWind_OnTick,
WizzrobeWind_OnCollision,
(void (*)(WizzrobeEntity*))GenericKnockback,
(void (*)(WizzrobeEntity*))GenericDeath,
(void (*)(WizzrobeEntity*))GenericConfused,
WizzrobeWind_OnTick,
};
void (*const WizzrobeWind_Actions[])(WizzrobeEntity*) = {
WizzrobeWind_Init,
WizzrobeWind_Action1,
WizzrobeWind_Action2,
WizzrobeWind_Action3,
};