/** * @file beanstalk.c * @ingroup Objects * * @brief Beanstalk object */ #define NENT_DEPRECATED #include "global.h" #include "object.h" #include "functions.h" typedef struct { /*0x00*/ Entity base; /*0x68*/ u8 unk_68[4]; /*0x6c*/ u32 unk_6c; /*0x70*/ u16 unk_70; /*0x72*/ u16 unk_72; } BeanstalkEntity; typedef struct { u8 type; s8 x; s8 y; u8 flipX; } struct_08120DFC; typedef struct { u8 unk_0; u8 unk_1; } struct_08120E3C; void Beanstalk_Action1(BeanstalkEntity*); void Beanstalk_Init(BeanstalkEntity*); void Beanstalk_Action1Type0(BeanstalkEntity*); void Beanstalk_Action1Type1(BeanstalkEntity*); void Beanstalk_Action1Type2(BeanstalkEntity*); void Beanstalk_Action1Type4(BeanstalkEntity*); void Beanstalk_Action1Type7(BeanstalkEntity*); void Beanstalk_Action1Type8(BeanstalkEntity*); void Beanstalk_Action1Type9(BeanstalkEntity*); void Beanstalk_Action1Type0SubAction0(BeanstalkEntity*); void Beanstalk_Action1Type0SubAction1(BeanstalkEntity*); void Beanstalk_Action1Type0SubAction2(BeanstalkEntity*); void Beanstalk_Action1Type8SubAction0(BeanstalkEntity*); void Beanstalk_Action1Type8SubAction1(BeanstalkEntity*); void Beanstalk(BeanstalkEntity* this) { static void (*const Beanstalk_Actions[])(BeanstalkEntity*) = { Beanstalk_Init, Beanstalk_Action1, }; Beanstalk_Actions[super->action](this); } const struct_08120DFC gUnk_08120DFC[] = { { 4, -2, 8, 0 }, { 6, 10, 16, 1 }, { 5, -4, 33, 0 }, { 6, -7, 7, 0 }, { 4, 5, 33, 1 }, { 5, 2, 37, 1 }, }; void Beanstalk_Init(BeanstalkEntity* this) { static const struct_08120E3C gUnk_08120E14[] = { { 0, 3 }, { 1, 3 }, { 0, 3 }, { 2, 3 }, { 3, 2 }, { 6, 2 }, { 9, 4 }, { 0, 3 }, { 0, 4 }, { 12, 6 }, }; static const struct_08120E3C gUnk_08120E3C[] = { { 1, 6 }, { 2, 6 }, { 4, 3 }, { 7, 5 }, { 10, 7 }, }; Entity* obj; const struct_08120DFC* ptr; super->spriteRendering.b3 = 2; super->spriteOrientation.flipY = 1; SetDefaultPriority(super, 4); if (super->type == 7) { #ifndef EU if ((super->flags & ENT_DID_INIT) == 0) { return; } #endif if (super->type2 == 0 && super->timer != 0) { if (CheckLocalFlag(super->timer) == 0) { return; } super->spriteOrientation.flipY = 2; } InitializeAnimation(super, gUnk_08120E3C[super->type2].unk_0); super->spritePriority.b0 = gUnk_08120E3C[super->type2].unk_1; } else { if (super->type != 0) { InitializeAnimation(super, gUnk_08120E14[super->type].unk_0); } else { LoadSwapGFX(super, 1, 2); InitAnimationForceUpdate(super, gUnk_08120E14[super->type].unk_0); } super->spritePriority.b0 = gUnk_08120E14[super->type].unk_1; } super->action = 1; super->spriteSettings.draw = 1; switch (super->type) { case 1: case 2: case 3: case 4: case 5: case 6: super->spriteVramOffset = 0x1c0; super->timer = 0; break; case 7: switch (super->type2) { case 0: this->unk_6c = 0x10; super->timer = 0; do { obj = CreateObject(BEANSTALK, 7, 1); super->child = obj; if (obj != NULL) { obj->x.HALF.HI = super->x.HALF.HI; (super->child)->y.HALF.HI = super->y.HALF.HI - (s16)this->unk_6c; super->subtimer = 4; while (--super->subtimer != 0) { ptr = &gUnk_08120DFC[super->timer]; obj = CreateObject(BEANSTALK, 7, ptr->type - 2); super->child = obj; if (obj != NULL) { obj->x.HALF.HI = super->x.HALF.HI + ptr->x; (super->child)->y.HALF.HI = (super->y.HALF.HI - (s16)this->unk_6c) - ptr->y; super->child->spriteSettings.flipX = ptr->flipX; } super->timer++; } if (super->timer > 5) { super->timer = 0; } } this->unk_6c += 0x38; } while (((s16)(super->y.HALF_U.HI - this->unk_6c)) >= gRoomControls.origin_y); super->timer = 1; break; case 2: case 3: super->spriteRendering.b3 = 1; // fallthrough case 4: super->collisionLayer = 3; } break; } Beanstalk_Action1(this); } void Beanstalk_Action1(BeanstalkEntity* this) { static void (*const Beanstalk_Action1Types[])(BeanstalkEntity*) = { Beanstalk_Action1Type0, Beanstalk_Action1Type1, Beanstalk_Action1Type2, Beanstalk_Action1Type1, Beanstalk_Action1Type4, Beanstalk_Action1Type4, Beanstalk_Action1Type4, Beanstalk_Action1Type7, Beanstalk_Action1Type8, Beanstalk_Action1Type9, }; Beanstalk_Action1Types[super->type](this); } void Beanstalk_Action1Type0(BeanstalkEntity* this) { static void (*const Beanstalk_Action1Type0SubActions[])(BeanstalkEntity*) = { Beanstalk_Action1Type0SubAction0, Beanstalk_Action1Type0SubAction1, Beanstalk_Action1Type0SubAction2, }; Beanstalk_Action1Type0SubActions[super->subAction](this); } void Beanstalk_Action1Type0SubAction0(BeanstalkEntity* this) { UpdateAnimationSingleFrame(super); if ((super->frame & ANIM_DONE) != 0) { if (super->timer < 2) { super->timer++; } else { InitAnimationForceUpdate(super, 1); super->timer = 0x10; super->subAction++; } } } void Beanstalk_Action1Type0SubAction1(BeanstalkEntity* this) { if (super->timer-- == 0) { super->timer = 0x10; SoundReq(SFX_198); } UpdateAnimationSingleFrame(super); if ((super->frame & ANIM_DONE) != 0) { Entity* entity = CreateObject(BEANSTALK, 1, 0); super->child = entity; if (entity != NULL) { entity->x.HALF.HI = super->x.HALF.HI; (super->child)->y.HALF.HI = super->y.HALF.HI; } entity = CreateObject(BEANSTALK, 2, 0); super->child = entity; if (entity != NULL) { entity->x.HALF.HI = super->x.HALF.HI; (super->child)->y.HALF.HI = super->y.HALF.HI + -0x10; } super->spriteSettings.draw = 0; super->subAction++; } } void Beanstalk_Action1Type0SubAction2(BeanstalkEntity* this) { if (super->timer-- == 0) { super->timer = 0x10; SoundReq(SFX_198); } } void Beanstalk_Action1Type2(BeanstalkEntity* this) { s32 tmp; const struct_08120DFC* ptr; GetNextFrame(super); if ((super->frame & 1) != 0) { ptr = &gUnk_08120DFC[super->timer]; super->child = CreateObject(BEANSTALK, ptr->type, 0); if (super->child != NULL) { super->child->x.HALF.HI = super->x.HALF.HI + ptr->x; super->child->y.HALF.HI = super->y.HALF.HI - ptr->y; super->child->spriteSettings.flipX = ptr->flipX; } if (++super->timer > 5) { super->timer = 0; } } if ((super->frame & ANIM_DONE) != 0) { super->child = CreateObject(BEANSTALK, 3, 0); if (super->child != NULL) { super->child->x.HALF.HI = super->x.HALF.HI; super->child->y.HALF.HI = super->y.HALF.HI; } tmp = super->y.HALF.HI -= 0x38; if (tmp * 0x10000 < 0) { DeleteEntity(super); } } } void Beanstalk_Action1Type4(BeanstalkEntity* this) { if ((super->frame & ANIM_DONE) == 0) { GetNextFrame(super); } } void Beanstalk_Action1Type1(BeanstalkEntity* this) { } void Beanstalk_Action1Type7(BeanstalkEntity* this) { switch (super->type2) { case 0: if (super->timer == 0) { return; } this->unk_6c = gRoomControls.origin_y; this->unk_70 = TILE(super->x.HALF.HI, this->unk_6c); while (TRUE) { this->unk_70 = TILE(super->x.HALF.HI, this->unk_6c); SetTile(0x4017, this->unk_70, 2); SetTile(0x4017, this->unk_70, 1); this->unk_6c += 0x10; if (this->unk_6c >= gRoomControls.origin_y + gRoomControls.height) break; if (this->unk_6c > super->y.HALF.HI) { break; } } super->timer = 0; return; break; case 1: return; case 2: case 3: case 4: if (gPlayerState.floor_type == SURFACE_LADDER) { if (EntityInRectRadius(super, &gPlayerEntity, 0, 8)) { if ((super->animIndex == (super->type2 - 1) * 3 + 1) && (super->timer == 0)) { super->timer = 1; InitializeAnimation(super, super->animIndex + 1); } } else { super->timer = 0; } } else { super->timer = 0; } GetNextFrame(super); if ((super->frame & ANIM_DONE) != 0) { InitializeAnimation(super, (super->type2 - 1) * 3 + 1); } break; } } void Beanstalk_Action1Type8(BeanstalkEntity* this) { static void (*const Beanstalk_Action1Type8SubActions[])(BeanstalkEntity*) = { Beanstalk_Action1Type8SubAction0, Beanstalk_Action1Type8SubAction1, }; Beanstalk_Action1Type8SubActions[super->subAction](this); } void Beanstalk_Action1Type8SubAction0(BeanstalkEntity* this) { Entity* obj; super->spriteOrientation.flipY = 2; this->unk_70 = COORD_TO_TILE(super); SetTile(0x4017, this->unk_70, 1); super->subAction = 1; obj = CreateObjectWithParent(super, OBJECT_15, 0, 0); if (obj != NULL) { obj->y.HALF.HI = super->y.HALF.HI + 0x38; obj->spriteIndex = super->spriteIndex; obj->spriteVramOffset = super->spriteVramOffset; obj->palette.b.b0 = super->palette.b.b0; obj->animIndex = 2; obj->timer = 0x80; obj->type = 1; obj->spriteRendering.b3 = 2; obj->spritePriority.b0 = 6; obj->spriteOrientation.flipY = 2; } CreateObjectWithParent(super, BEANSTALK, 9, 0); } void Beanstalk_Action1Type8SubAction1(BeanstalkEntity* this) { } void Beanstalk_Action1Type9(BeanstalkEntity* this) { if (super->subAction == 0) { super->subAction = 1; super->y.HALF.HI += 0x28; this->unk_72 = sub_080B1A0C(super, 0, -0x18); } super->spriteOrientation.flipY = gPlayerEntity.spriteOrientation.flipY; super->spriteRendering.b3 = gPlayerEntity.spriteRendering.b3; if (gPlayerState.floor_type == SURFACE_LADDER) { super->spritePriority.b0 = 0; if (sub_080B1A0C(super, 0, -0x18) != 0x4014) { SetTile(0x4014, COORD_TO_TILE_OFFSET(super, 0, 0x18), 1); } } else { super->spritePriority.b0 = 5; if (this->unk_72 != sub_080B1A0C(super, 0, -0x18)) { SetTile(this->unk_72, COORD_TO_TILE_OFFSET(super, 0, 0x18), 1); } } }