/** * @file pushableLever.c * @ingroup Objects * * @brief Pushable Lever object */ #define NENT_DEPRECATED #include "global.h" #include "object.h" #include "functions.h" typedef struct { /*0x00*/ Entity base; /*0x68*/ u8 unk_68[8]; /*0x70*/ u16 tilePosition; /*0x72*/ u16 tileIndex; /*0x74*/ u16 timer; /*0x76*/ u8 unk_76[16]; /*0x86*/ u16 pushedFlag; } PushableLeverEntity; enum PushableLeverAction { INIT, IDLE, PUSHING, }; extern void (*const PushableLever_Actions[])(PushableLeverEntity*); extern const u16 PushableLever_Tiles[]; extern const u8 PushableLever_InitialOffsets[]; extern const u8 PushableLever_PushedOffsets[]; void PushableLever_SetIdle(PushableLeverEntity*); bool32 PushableLever_ShouldStartPushing(PushableLeverEntity* this); void PushableLever_SetTiles(PushableLeverEntity*); void PushableLever_CalculateSpriteOffsets(PushableLeverEntity*); #define TILE_INITIAL 0x4053 #define TILE_PUSHED 0x4052 void PushableLever(PushableLeverEntity* this) { PushableLever_Actions[super->action](this); } void PushableLever_Init(PushableLeverEntity* this) { super->spritePriority.b0 = 5; PushableLever_SetIdle(this); } void PushableLever_Idle(PushableLeverEntity* this) { if (PushableLever_ShouldStartPushing(this)) { super->action = PUSHING; super->spriteOffsetX = 0; super->spriteOffsetY = 0; SetTile(this->tileIndex, this->tilePosition, super->collisionLayer); EnqueueSFX(SFX_16A); RequestPriorityDuration(super, 0x1e); if (sub_08079F8C()) { gPlayerState.pushedObject = 0x90; gPlayerState.queued_action = 5; gPlayerState.flags |= 1; gPlayerEntity.x.HALF.LO = 0; gPlayerEntity.y.HALF.LO = 0; gPlayerEntity.direction = gPlayerEntity.animationState << 2; } } } void PushableLever_Pushing(PushableLeverEntity* this) { GetNextFrame(super); if ((super->frame & 0x80) != 0) { if (super->type2 == 0) { SetFlag(this->pushedFlag); } else { ClearFlag(this->pushedFlag); } PushableLever_SetIdle(this); } } void PushableLever_SetIdle(PushableLeverEntity* this) { super->action = IDLE; this->timer = 0x3c; PushableLever_SetTiles(this); } void PushableLever_SetTiles(PushableLeverEntity* this) { if (CheckFlags(this->pushedFlag) == FALSE) { super->type2 = 0; this->tilePosition = COORD_TO_TILE_OFFSET(super, 0, 0x10); this->tileIndex = GetTileIndex(this->tilePosition, super->collisionLayer); SetTile(TILE_INITIAL, this->tilePosition, super->collisionLayer); InitializeAnimation(super, 1); } else { super->type2 = 1; this->tilePosition = COORD_TO_TILE_OFFSET(super, 0x10, 0); this->tileIndex = GetTileIndex(this->tilePosition, super->collisionLayer); SetTile(TILE_PUSHED, this->tilePosition, super->collisionLayer); InitializeAnimation(super, 0); } } bool32 PushableLever_ShouldStartPushing(PushableLeverEntity* this) { if (GetTileIndex(this->tilePosition, super->collisionLayer) == 0x4054) { if (--this->timer == 0) { return TRUE; } PushableLever_CalculateSpriteOffsets(this); SetTile(PushableLever_Tiles[super->type2], this->tilePosition, super->collisionLayer); } else { this->timer = 0x3c; super->spriteOffsetX = 0; super->spriteOffsetY = 0; } return FALSE; } void PushableLever_CalculateSpriteOffsets(PushableLeverEntity* this) { const u8* offsets; if (super->type2 == 0) { offsets = PushableLever_InitialOffsets; } else { offsets = PushableLever_PushedOffsets; } offsets = &offsets[(this->timer / 4) & 6]; super->spriteOffsetX = offsets[0]; super->spriteOffsetY = offsets[1]; if ((this->timer & 3) == 0) { EnqueueSFX(SFX_104); } } void (*const PushableLever_Actions[])(PushableLeverEntity*) = { PushableLever_Init, PushableLever_Idle, PushableLever_Pushing, }; const u16 PushableLever_Tiles[] = { TILE_INITIAL, TILE_PUSHED, }; const u8 PushableLever_InitialOffsets[] = { 0, 0, 0, 0, 255, 0, 0, 0, }; const u8 PushableLever_PushedOffsets[] = { 0, 0, 0, 0, 0, 255, 0, 0, };