Files
tmc/src/object/crenelBeanSprout.c
T
2022-12-22 23:47:13 +01:00

337 lines
12 KiB
C

/**
* @file crenelBeanSprout.c
* @ingroup Objects
*
* @brief Crenel Bean Sprout object
*/
#define NENT_DEPRECATED
#include "functions.h"
#include "global.h"
#include "hitbox.h"
#include "object.h"
typedef struct {
/*0x00*/ Entity base;
/*0x68*/ u8 unk_68[8];
/*0x70*/ u16 unk_70;
/*0x72*/ u16 unk_72;
} CrenelBeanSproutEntity;
extern u32 sub_080B1AB4(s32, s32, u32);
void sub_080969A4(CrenelBeanSproutEntity*);
void sub_08096A78(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Init(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action1(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action2(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action3(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action4(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action5(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action6(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action2SubAction0(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action2SubAction1(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action2SubAction2(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action2SubAction3(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action6SubAction0(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action6SubAction1(CrenelBeanSproutEntity*);
void CrenelBeanSprout_Action6SubAction2(CrenelBeanSproutEntity*);
void CrenelBeanSprout(CrenelBeanSproutEntity* this) {
static void (*const CrenelBeanSprout_Actions[])(CrenelBeanSproutEntity*) = {
CrenelBeanSprout_Init, CrenelBeanSprout_Action1, CrenelBeanSprout_Action2, CrenelBeanSprout_Action3,
CrenelBeanSprout_Action4, CrenelBeanSprout_Action5, CrenelBeanSprout_Action6,
};
CrenelBeanSprout_Actions[super->action](this);
}
void CrenelBeanSprout_Init(CrenelBeanSproutEntity* this) {
Entity* obj;
u32 tmp;
super->action = 1;
tmp = super->speed = 0x80;
super->hitbox = (Hitbox*)&gUnk_080FD2A8;
switch (super->type) {
case 0:
if (CheckGlobalFlag(WATERBEAN_OUT)) {
if (CheckGlobalFlag(WATERBEAN_PUT) == 0) {
PositionRelative(&gPlayerEntity, super, 0, 0x10000);
SetTile(0x4022, 0xdc, super->collisionLayer);
} else {
if (CheckLocalFlag(super->type2) == 0) {
InitializeAnimation(super, 10);
super->y.HALF.HI += 4;
super->action = 4;
SetTile(0x403b, COORD_TO_TILE(super), super->collisionLayer);
return;
}
super->type2 = 0;
super->subtimer = 2;
sub_080969A4(this);
DeleteThisEntity();
}
} else {
super->x.HALF.HI = gRoomControls.origin_x + 0xd0;
super->y.HALF.HI = gRoomControls.origin_y + 0x44;
super->action = 4;
InitializeAnimation(super, super->type + 3);
return;
}
break;
case 3:
if (CheckGlobalFlag(WATERBEAN_OUT)) {
if (CheckGlobalFlag(WATERBEAN_PUT) == 0) {
super->spritePriority.b0 = gPlayerEntity.spritePriority.b0 - 1;
*(((u8*)&gPlayerEntity) + 0x79) = tmp;
PositionRelative(&gPlayerEntity, super, 0, -0x180000);
} else {
DeleteThisEntity();
}
}
obj = CreateObjectWithParent(super, CRENEL_BEAN_SPROUT, 1, 0);
super->child = obj;
if (obj != NULL) {
PositionRelative(super, obj, -0x1c0000, -0x280000);
}
super->carryFlags = 0x10;
super->spriteRendering.b0 = 3;
InitializeAnimation(super, 0xc);
CrenelBeanSprout_Action1(this);
return;
break;
case 1:
super->spriteRendering.b0 = 3;
SetDefaultPriority(super, 6);
break;
case 2:
if (CheckLocalFlag((u32)super->type2) == 0) {
InitializeAnimation(super, 0xb);
super->y.HALF.HI += 4;
super->action = 4;
SetTile(0x4032, COORD_TO_TILE(super), super->collisionLayer);
return;
} else {
super->type2 = 0;
super->subtimer = 3;
sub_080969A4(this);
DeleteThisEntity();
return;
}
break;
}
InitializeAnimation(super, super->type + 3);
CrenelBeanSprout_Action1(this);
}
void CrenelBeanSprout_Action1(CrenelBeanSproutEntity* this) {
static const u8 gUnk_08123184[] = {
0, 240, 16, 0, 0, 16, 240, 0,
};
Entity* parent;
u32 tmp;
if ((super->type & 1) != 0) {
if (super->type == 3) {
RegisterCarryEntity(super);
sub_0800445C(super);
} else {
PositionRelative(super->parent, super, -0x1c0000, -0x280000);
if (super->parent->action == 2) {
switch (super->parent->subAction) {
case 1:
if ((gPlayerState.direction & 0x80) != 0) {
InitializeAnimation(super, 4);
} else {
GetNextFrame(super);
}
break;
case 2:
GetNextFrame(super);
break;
default:
InitializeAnimation(super, 4);
break;
}
}
super->spritePriority.b0 = super->parent->spritePriority.b0 - 1;
parent = super->parent;
super->spriteRendering.b3 = parent->spriteRendering.b3;
super->spriteOrientation.flipY = parent->spriteOrientation.flipY;
}
SetAffineInfo(super, 0xcc, 0xcc, 0);
} else {
gPlayerState.mobility |= 0x80;
gPlayerState.heldObject = 5;
if ((gPlayerState.direction & 0x80) != 0) {
InitializeAnimation(super, (super->type >> 1) + 3);
} else {
GetNextFrame(super);
}
tmp = gPlayerEntity.animationState & 6;
this->unk_70 = ((super->x.HALF.HI + (s8)gUnk_08123184[tmp]) & -0x10) | 8;
this->unk_72 = ((super->y.HALF.HI + (s8)gUnk_08123184[(tmp) + 1]) & -0x10) | 8;
if (sub_080B1AB4(this->unk_70, this->unk_72, super->collisionLayer) == 0x19) {
gHUD.unk_2f = 3;
} else {
gHUD.unk_2f = 0;
}
PositionRelative(&gPlayerEntity, super, 0, 0x10000);
if (GetTileUnderEntity(super) == 0x19) {
RestorePrevTileEntity(0xdc, super->collisionLayer);
sub_08096A78(this);
}
if ((gPlayerState.playerInput.newInput & (PLAYER_INPUT_80 | PLAYER_INPUT_40)) == 0) {
return;
}
if (gHUD.unk_2f != 3) {
return;
}
gPlayerState.heldObject = 0;
super->action = 5;
super->speed = 0x100;
super->zVelocity = Q_16_16(2);
super->spritePriority.b1 = 1;
super->spriteSettings.shadow = 1;
RestorePrevTileEntity(0xdc, super->collisionLayer);
SoundReq(SFX_PLY_VO5);
}
}
void CrenelBeanSprout_Action2(CrenelBeanSproutEntity* this) {
static void (*const CrenelBeanSprout_Action2SubActions[])(CrenelBeanSproutEntity*) = {
CrenelBeanSprout_Action2SubAction0,
CrenelBeanSprout_Action2SubAction1,
CrenelBeanSprout_Action2SubAction2,
CrenelBeanSprout_Action2SubAction3,
};
CrenelBeanSprout_Action2SubActions[super->subAction](this);
}
void CrenelBeanSprout_Action2SubAction0(CrenelBeanSproutEntity* this) {
SetGlobalFlag(WATERBEAN_OUT);
super->subAction++;
}
void CrenelBeanSprout_Action2SubAction1(CrenelBeanSproutEntity* this) {
}
void CrenelBeanSprout_Action2SubAction2(CrenelBeanSproutEntity* this) {
ClearGlobalFlag(WATERBEAN_OUT);
}
void CrenelBeanSprout_Action2SubAction3(CrenelBeanSproutEntity* this) {
InitScreenShake(16, 0);
super->action = 1;
super->subAction = 0;
}
void CrenelBeanSprout_Action3(CrenelBeanSproutEntity* this) {
UpdateAnimationSingleFrame(super);
if ((super->frame & ANIM_DONE) != 0) {
super->action++;
InitializeAnimation(super, 10);
}
}
void CrenelBeanSprout_Action4(CrenelBeanSproutEntity* this) {
static const u16 gUnk_0812319C[] = { 0x403c, 0x4033 };
if (gUnk_0812319C[super->type >> 1] == GetTileTypeByEntity(super)) {
GetNextFrame(super);
gPlayerState.keepFacing |= 0x80;
gPlayerState.field_0xa |= 0x80;
gPlayerState.field_0x7 |= 0x80;
if (--super->timer == 0) {
super->action = 6;
super->subAction = 0;
CreateDust(super);
}
} else {
super->timer = 192;
}
}
void CrenelBeanSprout_Action5(CrenelBeanSproutEntity* this) {
if ((this->unk_70 != super->x.HALF.HI) || (this->unk_72 != super->y.HALF.HI)) {
super->direction = CalculateDirectionTo(super->x.HALF.HI, super->y.HALF.HI, this->unk_70, this->unk_72);
LinearMoveUpdate(super);
}
if (GravityUpdate(super, Q_8_8(64.0)) == 0) {
sub_08096A78(this);
}
}
void CrenelBeanSprout_Action6(CrenelBeanSproutEntity* this) {
static void (*const CrenelBeanSprout_Action6SubActions[])(CrenelBeanSproutEntity*) = {
CrenelBeanSprout_Action6SubAction0,
CrenelBeanSprout_Action6SubAction1,
CrenelBeanSprout_Action6SubAction2,
};
if (super->subAction != 2) {
sub_08078B48();
}
CrenelBeanSprout_Action6SubActions[super->subAction](this);
}
void CrenelBeanSprout_Action6SubAction0(CrenelBeanSproutEntity* this) {
static const u8 gUnk_081231AC[] = { 2, 3 };
SetLocalFlag(super->type2);
super->timer = 15;
super->subtimer = gUnk_081231AC[super->type >> 1];
super->type2 = 0;
super->spriteSettings.draw = 0;
super->subAction++;
if (super->type == 0) {
sub_0807B7D8(0x1ce, COORD_TO_TILE(super), super->collisionLayer);
} else {
sub_0807B7D8(0x1cd, COORD_TO_TILE(super), super->collisionLayer);
}
SoundReq(SFX_1DB);
}
void CrenelBeanSprout_Action6SubAction1(CrenelBeanSproutEntity* this) {
static const u16 gUnk_081231AE[] = { 0x1cc, 0x1cb, 0x1c9 };
if (--super->timer == 0) {
super->y.HALF.HI += -0x10;
sub_0807B7D8(gUnk_081231AE[super->type2], COORD_TO_TILE(super), super->collisionLayer);
super->type2++;
if (super->type2 == super->subtimer) {
gPlayerState.keepFacing &= ~0x80;
super->subAction++;
super->timer = 60;
} else {
super->timer = 15;
}
}
}
void CrenelBeanSprout_Action6SubAction2(CrenelBeanSproutEntity* this) {
if ((super->timer != 0) && (--super->timer == 0)) {
SoundReq(SFX_SECRET);
}
}
void sub_080969A4(CrenelBeanSproutEntity* this) {
static const u16 gUnk_081231B4[] = { 0x1cc, 0x1cb, 0x1c9 };
if (super->type == 0) {
sub_0807B7D8(0x1ce, COORD_TO_TILE(super), super->collisionLayer);
} else {
sub_0807B7D8(0x1cd, COORD_TO_TILE(super), super->collisionLayer);
}
while (super->type2 != super->subtimer) {
super->y.HALF.HI -= 0x10;
sub_0807B7D8(gUnk_081231B4[super->type2], COORD_TO_TILE(super), super->collisionLayer);
super->type2++;
}
}
void sub_08096A78(CrenelBeanSproutEntity* this) {
SetGlobalFlag(WATERBEAN_PUT);
InitAnimationForceUpdate(super, (super->type >> 1) + 8);
sub_08004168(super);
super->y.HALF.HI += 4;
super->action = 3;
SetTile(0x403b, COORD_TO_TILE(super), super->collisionLayer);
}