mirror of https://github.com/zeldaret/tmc.git
412 lines
13 KiB
C
412 lines
13 KiB
C
/**
|
|
* @file pullableMushroom.c
|
|
* @ingroup Objects
|
|
*
|
|
* @brief Pullable Mushroom object
|
|
*/
|
|
|
|
#define NENT_DEPRECATED
|
|
#include "global.h"
|
|
#include "object.h"
|
|
#include "functions.h"
|
|
#include "game.h"
|
|
#include "hitbox.h"
|
|
|
|
typedef struct {
|
|
/*0x00*/ Entity base;
|
|
/*0x68*/ u8 unk_68[0x8];
|
|
/*0x70*/ u32 unk_70;
|
|
/*0x74*/ u32 unk_74;
|
|
/*0x78*/ u32 unk_78;
|
|
/*0x7c*/ u32 unk_7c;
|
|
} PullableMushroomEntity;
|
|
|
|
extern const u8 gUnk_08126EE4[];
|
|
|
|
void PullableMushroom_Init(PullableMushroomEntity*);
|
|
void PullableMushroom_Action1(PullableMushroomEntity*);
|
|
void PullableMushroom_Action2(PullableMushroomEntity*);
|
|
void PullableMushroom_Action3(PullableMushroomEntity*);
|
|
void PullableMushroom_Action1_Type0(PullableMushroomEntity*);
|
|
void PullableMushroom_Action1_Type1(PullableMushroomEntity*);
|
|
void sub_0808ABC4(PullableMushroomEntity*);
|
|
void sub_0808ACEC(PullableMushroomEntity*);
|
|
void sub_0808ADA0(PullableMushroomEntity*);
|
|
void sub_0808ADF0(PullableMushroomEntity*);
|
|
void sub_0808AEB0(PullableMushroomEntity*);
|
|
void sub_0808AFD4(PullableMushroomEntity*);
|
|
void sub_0808B05C(PullableMushroomEntity*);
|
|
void sub_0808B0BC(PullableMushroomEntity*);
|
|
void sub_0808B168(PullableMushroomEntity*, u32);
|
|
u32 sub_0808B1F0(PullableMushroomEntity*, Entity*);
|
|
bool32 sub_0808B21C(PullableMushroomEntity*, u32);
|
|
|
|
void PullableMushroom(PullableMushroomEntity* this) {
|
|
static void (*const PullableMushroom_Actions[])(PullableMushroomEntity*) = {
|
|
PullableMushroom_Init,
|
|
PullableMushroom_Action1,
|
|
PullableMushroom_Action2,
|
|
PullableMushroom_Action3,
|
|
};
|
|
PullableMushroom_Actions[super->action](this);
|
|
super->bitfield = 0;
|
|
}
|
|
|
|
void PullableMushroom_Init(PullableMushroomEntity* this) {
|
|
super->action = 1;
|
|
if (AreaIsDungeon() == 0) {
|
|
ChangeObjPalette(super, 0);
|
|
}
|
|
switch (super->type) {
|
|
case 0:
|
|
super->spritePriority.b0 = 4;
|
|
super->hitbox = (Hitbox*)&gUnk_080FD224;
|
|
super->field_0x16 = 1;
|
|
SetTile(0x4022, COORD_TO_TILE(super), super->collisionLayer);
|
|
super->health = 1;
|
|
super->field_0x3c = 7;
|
|
super->hitType = 0x6e;
|
|
super->flags2 = 0x0e;
|
|
super->field_0x1c = 1;
|
|
super->flags |= 0x80;
|
|
super->spriteOffsetY = 4;
|
|
break;
|
|
case 1:
|
|
super->spritePriority.b0 = 4;
|
|
if (super->type2 != 0) {
|
|
super->hitbox = (Hitbox*)&gUnk_080FD224;
|
|
super->flags |= 0x80;
|
|
super->health = 1;
|
|
super->field_0x3c = 7;
|
|
super->hitType = 0x6e;
|
|
super->flags2 = 4;
|
|
super->field_0x1c = 1;
|
|
super->action = 3;
|
|
}
|
|
InitializeAnimation(super, super->animationState + 9);
|
|
break;
|
|
case 2:
|
|
super->spritePriority.b0 = 5;
|
|
super->spriteRendering.b0 = 3;
|
|
if ((super->animationState & 1)) {
|
|
this->unk_74 = 0x200;
|
|
this->unk_78 = 0x100;
|
|
} else {
|
|
this->unk_78 = 0x200;
|
|
this->unk_74 = 0x100;
|
|
}
|
|
break;
|
|
}
|
|
PullableMushroom_Action1(this);
|
|
}
|
|
|
|
void PullableMushroom_Action1(PullableMushroomEntity* this) {
|
|
static void (*const funcs[])(PullableMushroomEntity*) = {
|
|
PullableMushroom_Action1_Type0,
|
|
PullableMushroom_Action1_Type1,
|
|
sub_0808ABC4,
|
|
};
|
|
funcs[super->type](this);
|
|
}
|
|
|
|
void PullableMushroom_Action1_Type0(PullableMushroomEntity* this) {
|
|
static void (*const funcs[])(PullableMushroomEntity*) = {
|
|
sub_0808ACEC,
|
|
sub_0808ADA0,
|
|
sub_0808ADF0,
|
|
};
|
|
funcs[super->subAction](this);
|
|
}
|
|
|
|
void PullableMushroom_Action1_Type1(PullableMushroomEntity* this) {
|
|
if (*(u16*)&super->parent->action == 0x201) {
|
|
super->parent->child = NULL;
|
|
DeleteThisEntity();
|
|
} else if (super->parent->action == 2) {
|
|
sub_0808B168(this, 0);
|
|
}
|
|
}
|
|
|
|
const u16 gUnk_081211CC[] = { 32768, 64000, 0, 64517, 0, 0, 32768, 64763 };
|
|
ASM_FUNC("asm/non_matching/pullableMushroom/sub_0808ABC4.inc", void sub_0808ABC4(PullableMushroomEntity* this))
|
|
|
|
void sub_0808ACEC(PullableMushroomEntity* this) {
|
|
if (super->animIndex != 0) {
|
|
InitializeAnimation(super, 0);
|
|
}
|
|
|
|
switch (super->bitfield & 0x7f) {
|
|
case 0x4:
|
|
case 0x5:
|
|
case 0x6:
|
|
case 0x8:
|
|
case 0x9:
|
|
case 0xa:
|
|
case 0xb:
|
|
case 0xc:
|
|
case 0xd:
|
|
case 0x10:
|
|
case 0x11:
|
|
case 0x12:
|
|
case 0x14:
|
|
case 0x16:
|
|
COLLISION_OFF(super);
|
|
super->animationState = sub_0806F5A4(super->knockbackDirection);
|
|
super->subAction = 2;
|
|
super->actionDelay = 2;
|
|
break;
|
|
case 0x13:
|
|
super->action = 3;
|
|
super->subAction = 0;
|
|
break;
|
|
default:
|
|
super->field_0xf = 0;
|
|
super->actionDelay = 0;
|
|
RegisterCarryEntity(super);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void sub_0808ADA0(PullableMushroomEntity* this) {
|
|
if ((sub_0808B1F0(this, super->child) < 8) || (super->child == NULL)) {
|
|
super->subAction += 1;
|
|
super->actionDelay = 2;
|
|
super->flags |= ENT_COLLIDE;
|
|
super->animationState ^= 2;
|
|
super->spritePriority.b0 = 4;
|
|
} else {
|
|
super->child->speed = 0x400;
|
|
LinearMoveUpdate(super->child);
|
|
}
|
|
}
|
|
|
|
void sub_0808ADF0(PullableMushroomEntity* this) {
|
|
if (super->animationState + 0xd == super->animIndex) {
|
|
if ((super->frame & ANIM_DONE) != 0) {
|
|
super->subAction = 0;
|
|
super->flags |= ENT_COLLIDE;
|
|
} else {
|
|
GetNextFrame(super);
|
|
}
|
|
} else {
|
|
if (super->animationState + 1 != super->animIndex) {
|
|
InitializeAnimation(super, super->animationState + 1);
|
|
if (super->animationState == 3) {
|
|
super->spriteSettings.flipX = 0;
|
|
} else {
|
|
super->spriteSettings.flipX = 1;
|
|
}
|
|
SoundReq(SFX_12E);
|
|
} else {
|
|
GetNextFrame(super);
|
|
if (((super->frame & ANIM_DONE) != 0) && (--super->actionDelay == 0xff)) {
|
|
InitializeAnimation(super, super->animationState + 0xd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PullableMushroom_Action2(PullableMushroomEntity* this) {
|
|
static void (*const funcs[])(PullableMushroomEntity*) = {
|
|
sub_0808AEB0,
|
|
sub_0808AFD4,
|
|
};
|
|
if (gPlayerState.heldObject == 0) {
|
|
super->subAction = 6;
|
|
}
|
|
funcs[super->subAction - 5](this);
|
|
}
|
|
|
|
void sub_0808AEB0(PullableMushroomEntity* this) {
|
|
static const u16 gUnk_081211E4[] = { 1024, 256, 2048, 512 };
|
|
u32 uVar1;
|
|
if (super->actionDelay != 0) {
|
|
uVar1 = sub_0808B1F0(this, super->child);
|
|
if ((gPlayerState.field_0x90 & gUnk_081211E4[super->animationState]) != 0) {
|
|
GetNextFrame(super);
|
|
if (uVar1 < 0x40) {
|
|
sub_080044AE(&gPlayerEntity, 0x40, super->direction);
|
|
if (--this->unk_7c == 0xffffffff) {
|
|
this->unk_7c = 4;
|
|
SoundReq(SFX_12F);
|
|
}
|
|
}
|
|
super->field_0xf = 1;
|
|
|
|
} else {
|
|
if (((super->field_0xf != 0) && (gPlayerEntity.action == 1)) && (gPlayerState.swim_state == 0)) {
|
|
gPlayerState.queued_action = 0x1b;
|
|
gPlayerState.field_0x38 = uVar1;
|
|
gPlayerState.field_0x39 = super->direction ^ 0x10;
|
|
gPlayerState.field_0x3a = sub_0808B1F0(this, &gPlayerEntity);
|
|
super->subAction++;
|
|
}
|
|
}
|
|
} else {
|
|
super->actionDelay = 1;
|
|
this->unk_7c = 1;
|
|
super->animationState = AnimationStateFlip90(gPlayerEntity.animationState >> 1);
|
|
super->direction = (super->animationState << 3);
|
|
super->flags &= 0x7f;
|
|
super->spriteSettings.flipX = gPlayerEntity.spriteSettings.flipX;
|
|
InitializeAnimation(super, super->animationState + 5);
|
|
if (sub_0808B21C(this, 0)) {
|
|
sub_0808B168((PullableMushroomEntity*)super->child, 0);
|
|
}
|
|
if ((super->animationState & 1) != 0) {
|
|
gPlayerEntity.y.HALF.HI = super->y.HALF.HI;
|
|
} else {
|
|
gPlayerEntity.x.HALF.HI = super->x.HALF.HI;
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_0808AFD4(PullableMushroomEntity* this) {
|
|
super->action = 1;
|
|
super->subAction = 1;
|
|
(super->child)->direction = DirectionTurnAround(super->direction);
|
|
SoundReq(SFX_130);
|
|
}
|
|
|
|
void PullableMushroom_Action3(PullableMushroomEntity* this) {
|
|
static void (*const funcs[])(PullableMushroomEntity*) = {
|
|
sub_0808B05C,
|
|
sub_0808B0BC,
|
|
};
|
|
|
|
funcs[super->subAction](this);
|
|
if ((((gPlayerState.field_0x1c & 0xf) != 1) || ((super->bitfield & 0x7f) != 0x13)) && (super->type == 1)) {
|
|
(super->parent)->action = 1;
|
|
(super->parent)->subAction = 1;
|
|
super->direction = DirectionTurnAround(super->parent->direction);
|
|
super->parent->flags &= ~ENT_COLLIDE;
|
|
super->flags &= ~ENT_COLLIDE;
|
|
super->action = 1;
|
|
SoundReq(SFX_130);
|
|
}
|
|
}
|
|
|
|
void sub_0808B05C(PullableMushroomEntity* this) {
|
|
if (super->type == 0) {
|
|
super->animationState = AnimationStateFlip90(gPlayerEntity.animationState >> 1);
|
|
super->direction = super->animationState << 3;
|
|
super->spriteSettings.flipX = gPlayerEntity.spriteSettings.flipX;
|
|
super->flags &= 0x7f;
|
|
InitializeAnimation(super, super->animationState + 5);
|
|
if (sub_0808B21C(this, 1)) {
|
|
sub_0808B168((PullableMushroomEntity*)super->child, 1);
|
|
}
|
|
}
|
|
super->subAction++;
|
|
}
|
|
|
|
void sub_0808B0BC(PullableMushroomEntity* this) {
|
|
u32 uVar2;
|
|
const s8* ptr;
|
|
GenericEntity ent;
|
|
|
|
uVar2 = sub_0808B1F0(this, super->parent);
|
|
switch (super->type) {
|
|
case 0:
|
|
GetNextFrame(super);
|
|
break;
|
|
case 1:
|
|
ptr = &gUnk_08126EE4[gPlayerEntity.animationState & 0xe];
|
|
ent.base.x.HALF.HI = ptr[0] + gPlayerEntity.x.HALF.HI;
|
|
ent.base.y.HALF.HI = ptr[1] + gPlayerEntity.y.HALF.HI;
|
|
if (sub_0800419C(&ent.base, super, 7, 7)) {
|
|
if ((gPlayerEntity.action != 1) || (gPlayerState.swim_state != 0))
|
|
return;
|
|
gPlayerState.queued_action = 0x1b;
|
|
gPlayerState.field_0x38 = uVar2;
|
|
gPlayerState.field_0x39 = super->direction ^ 0x10;
|
|
gPlayerState.field_0x3a = sub_0808B1F0((PullableMushroomEntity*)super->parent, &gPlayerEntity);
|
|
} else {
|
|
super->speed = 0x40;
|
|
if (uVar2 < 0x40) {
|
|
LinearMoveUpdate(super);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void sub_0808B168(PullableMushroomEntity* this, u32 param_2) {
|
|
static const s8 gUnk_081211F4[] = {
|
|
0, 8, -8, -4, 0, -8, 8, -4,
|
|
};
|
|
static const s8 gUnk_081211FC[] = {
|
|
0, 3, -8, -4, 0, -12, 8, -4,
|
|
};
|
|
s32 iVar2;
|
|
const s8* pcVar3;
|
|
u32 uVar4;
|
|
const s8* pcVar5;
|
|
Entity* pEVar5;
|
|
Entity* pEVar6;
|
|
|
|
if (param_2 != 0) {
|
|
iVar2 = AnimationStateFlip90(super->animationState) * 2;
|
|
pcVar5 = (gUnk_081211F4 + iVar2);
|
|
pcVar3 = pcVar5 + 1;
|
|
pEVar5 = super->parent;
|
|
pEVar6 = pEVar5;
|
|
} else {
|
|
if ((super->animationState & 1) != 0) {
|
|
pEVar6 = &gPlayerEntity;
|
|
pEVar5 = super->parent;
|
|
pcVar5 = (gUnk_081211FC + super->animationState * 2);
|
|
pcVar3 = (gUnk_081211F4 + 1 + AnimationStateFlip90(super->animationState) * 2);
|
|
} else {
|
|
pEVar6 = super->parent;
|
|
pEVar5 = &gPlayerEntity;
|
|
pcVar5 = (gUnk_081211F4 + AnimationStateFlip90(super->animationState) * 2);
|
|
pcVar3 = (gUnk_081211FC + 1 + super->animationState * 2);
|
|
}
|
|
}
|
|
super->x.HALF.HI = *pcVar5 + pEVar6->x.HALF.HI;
|
|
super->y.HALF.HI = *pcVar3 + pEVar5->y.HALF.HI;
|
|
}
|
|
|
|
u32 sub_0808B1F0(PullableMushroomEntity* this, Entity* other) {
|
|
s32 sVar1;
|
|
s32 sVar2;
|
|
u32 uVar3;
|
|
|
|
if ((super->animationState & 1) != 0) {
|
|
sVar1 = super->x.HALF.HI;
|
|
sVar2 = other->x.HALF.HI;
|
|
} else {
|
|
sVar1 = super->y.HALF.HI;
|
|
sVar2 = other->y.HALF.HI;
|
|
}
|
|
uVar3 = (s32)sVar1 - (s32)sVar2;
|
|
if ((s32)uVar3 < 0) {
|
|
uVar3 = -uVar3;
|
|
}
|
|
return uVar3;
|
|
}
|
|
|
|
bool32 sub_0808B21C(PullableMushroomEntity* this, u32 param_2) {
|
|
Entity* obj;
|
|
|
|
super->spritePriority.b0 = 6;
|
|
obj = CreateObjectWithParent(super, PULLABLE_MUSHROOM, 1, 0);
|
|
super->child = obj;
|
|
if (obj != NULL) {
|
|
obj->animationState = super->animationState;
|
|
(super->child)->direction = super->direction;
|
|
super->child->spriteSettings.flipX = super->spriteSettings.flipX;
|
|
(super->child)->parent = super;
|
|
(super->child)->type2 = (u8)param_2;
|
|
}
|
|
obj = CreateObjectWithParent(super, PULLABLE_MUSHROOM, 2, 0);
|
|
super->parent = obj;
|
|
if (obj != NULL) {
|
|
obj->animationState = super->animationState;
|
|
(super->parent)->child = super->child;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|