Files
tmc/src/object/pushableLever.c
T
2022-01-24 21:33:30 +01:00

149 lines
4.2 KiB
C

/**
* @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,
};