tmc/src/object/pullableLever.c

285 lines
8.5 KiB
C

/**
* @file pullableLever.c
* @ingroup Objects
*
* @brief Pullable Lever object
*/
#define NENT_DEPRECATED
#include "global.h"
#include "object.h"
#include "functions.h"
#include "sound.h"
typedef struct {
/*0x00*/ Entity base;
/*0x68*/ u8 unk_68[8];
/*0x70*/ u16 pullLength;
/*0x72*/ u16 leverPart; // lever part number? [0,1,2]
/*0x74*/ u8 actionDelay;
/*0x75*/ u8 unk_75;
/*0x76*/ u16 necessaryPullLength;
/*0x78*/ u8 unk_78[6];
/*0x7e*/ u8 unk_7e;
/*0x7f*/ u8 unk_7f;
/*0x80*/ u16 initialX;
/*0x82*/ u16 initialY;
/*0x84*/ u8 unk_84[2];
/*0x86*/ u16 pulledFlag;
} PullableLeverEntity;
enum PullableLeverPart { HANDLE, MIDDLE, SOCKET };
extern u16 gUnk_02021F00[];
extern Hitbox gUnk_080FD270;
extern Hitbox gUnk_080FD278;
extern void (*const PullableLever_HandleActions[])(PullableLeverEntity*);
extern void (*const PullableLever_MiddleActions[])(PullableLeverEntity*);
extern const s8 PullableLever_InitialOffsets[];
extern void (*const PullableLever_HandleSubActions[])(PullableLeverEntity*);
extern const s8 gUnk_081222B8[];
extern const u8 gUnk_081222C0[];
void sub_08091504(PullableLeverEntity*);
void PullableLever_UpdateLength(PullableLeverEntity*);
void sub_0809153C(PullableLeverEntity*);
void PullableLever(PullableLeverEntity* this) {
switch (this->leverPart) {
case HANDLE:
PullableLever_HandleActions[super->action](this);
sub_0800445C(super);
gUnk_02021F00[this->actionDelay] = this->pullLength;
break;
case MIDDLE:
PullableLever_MiddleActions[super->action](this);
break;
case SOCKET:
if (super->action == 0) {
sub_08091504(this);
}
break;
}
}
void PullableLever_HandleInit(PullableLeverEntity* this) {
if (gEntCount < 0x46) {
PullableLeverEntity* entity1 = (PullableLeverEntity*)CreateObject(PULLABLE_LEVER, super->type, super->type2);
PullableLeverEntity* entity2 = (PullableLeverEntity*)CreateObject(PULLABLE_LEVER, super->type, super->type2);
(entity1->base).parent = super;
(entity2->base).parent = super;
entity1->leverPart = 1;
entity2->leverPart = 2;
CopyPosition(super, &entity2->base);
super->action = 1;
super->spriteSettings.draw = 1;
super->speed = 0x60;
if ((super->type2 & 1)) {
super->hitbox = &gUnk_080FD278;
} else {
super->hitbox = &gUnk_080FD270;
}
super->field_0x16 = 1;
super->x.HALF.HI += PullableLever_InitialOffsets[super->type2 * 2];
this->initialX = super->x.HALF.HI;
super->y.HALF.HI += PullableLever_InitialOffsets[super->type2 * 2 + 1];
this->initialY = super->y.HALF.HI;
CopyPosition(super, &entity1->base);
this->necessaryPullLength = this->unk_7e;
this->actionDelay = super->actionDelay;
InitializeAnimation(super, super->type2);
}
}
void PullableLever_HandleAction1(PullableLeverEntity* this) {
sub_08078930(super);
if (this->pullLength != 0) {
super->direction = super->type2 << 3;
LinearMoveUpdate(super);
PullableLever_UpdateLength(this);
}
}
void PullableLever_HandleAction2(PullableLeverEntity* this) {
sub_0806FBB4(super);
PullableLever_HandleSubActions[super->subAction - 5](this);
}
void PullableLever_HandleSubAction0(PullableLeverEntity* this) {
u16 y;
u16 x;
Entity* player = &gPlayerEntity;
if (this->unk_75 == 0) {
if (-player->animationState + super->type2 * 2 == 0) {
x = gUnk_081222B8[super->type2 * 2] + super->x.HALF_U.HI;
y = gUnk_081222B8[super->type2 * 2 + 1] + super->y.HALF_U.HI;
if (0x10 < sub_080002D4(x, y, player->collisionLayer) - 0xf) {
player->x.HALF.HI = x;
player->y.HALF.HI = y;
}
}
this->unk_75 = 1;
super->field_0xf = 2;
}
if (player->animationState >> 1 == super->type2) {
if (gPlayerState.framestate == PL_STATE_PULL) {
if (gPlayerState.heldObject & 2) {
if (gPlayerEntity.frame & 2) {
sub_0809153C(this);
if (this->unk_75 == 1) {
this->unk_75 = 2;
EnqueueSFX(SFX_19E);
}
}
}
}
}
}
void PullableLever_HandleSubAction1(PullableLeverEntity* this) {
super->action = 1;
this->unk_75 = 0;
}
void PullableLever_MiddleInit(PullableLeverEntity* this) {
super->action = 1;
super->spritePriority.b0 = 5;
InitializeAnimation(super, super->parent->type2 + 8);
UpdateSpriteForCollisionLayer(super);
}
void PullableLever_MiddleAction1(PullableLeverEntity* this) {
u16 tmp;
PullableLeverEntity* parent = ((PullableLeverEntity*)super->parent);
if (parent->pullLength < 8) {
super->spriteSettings.draw = 0;
} else {
super->spriteSettings.draw = 1;
tmp = (((PullableLeverEntity*)super->parent)->pullLength - 8) & 7;
switch (super->type2) {
case 0:
super->y.HALF.HI = (super->parent->y.HALF.HI - tmp) - 0x11;
break;
case 1:
super->x.HALF.HI = tmp + super->parent->x.HALF.HI + 0x11;
break;
case 2:
super->y.HALF.HI = tmp + super->parent->y.HALF.HI + 0x11;
break;
case 3:
super->x.HALF.HI = (super->parent->x.HALF.HI - tmp) - 0x11;
break;
}
tmp = (parent->pullLength - 8) >> 4;
if (tmp != super->animationState) {
super->animationState = tmp;
InitializeAnimation(super, tmp * 4 + super->type2 + 8);
}
}
}
void sub_08091504(PullableLeverEntity* this) {
super->action = 1;
super->spriteSettings.draw = 1;
super->spritePriority.b0 = 6;
InitializeAnimation(super, super->type2 + 4);
UpdateSpriteForCollisionLayer(super);
}
void sub_0809153C(PullableLeverEntity* this) {
s16 prevX;
s16 prevY;
u32 dir;
s16 diff;
s32 radius;
Entity* player = &gPlayerEntity;
dir = gUnk_081222C0[super->type2];
if (this->necessaryPullLength <= this->pullLength) {
return;
}
prevX = player->x.HALF.HI;
prevY = player->y.HALF.HI;
sub_080044AE(&gPlayerEntity, super->speed, dir);
if ((prevX == gPlayerEntity.x.HALF.HI) && (prevY == gPlayerEntity.y.HALF.HI)) {
return;
}
switch (super->type2) {
case 0:
diff = player->y.HALF.HI - prevY;
break;
case 1:
diff = prevX - gPlayerEntity.x.HALF.HI;
break;
case 2:
diff = prevY - gPlayerEntity.y.HALF.HI;
break;
case 3:
diff = gPlayerEntity.x.HALF.HI - prevX;
break;
}
radius = (diff << 0x18);
super->x.WORD += gSineTable[dir * 8] * (radius >> 0x10);
super->y.WORD -= gSineTable[dir * 8 + 0x40] * (radius >> 0x10);
PullableLever_UpdateLength(this);
if (this->necessaryPullLength <= this->pullLength) {
EnqueueSFX(SFX_BUTTON_PRESS);
SetFlag(this->pulledFlag);
} else {
if (--super->field_0xf == 0) {
super->field_0xf = 0x10;
EnqueueSFX(SFX_10F);
}
}
}
void PullableLever_UpdateLength(PullableLeverEntity* this) {
switch (super->type2) {
case 0:
this->pullLength = super->y.HALF.HI - this->initialY;
break;
case 1:
this->pullLength = this->initialX - super->x.HALF.HI;
break;
case 2:
this->pullLength = this->initialY - super->y.HALF.HI;
break;
case 3:
this->pullLength = super->x.HALF.HI - this->initialX;
break;
}
if (CheckFlags(this->pulledFlag) && (this->pullLength == 0)) {
ClearFlag(this->pulledFlag);
}
}
void (*const PullableLever_HandleActions[])(PullableLeverEntity*) = {
PullableLever_HandleInit,
PullableLever_HandleAction1,
PullableLever_HandleAction2,
};
void (*const PullableLever_MiddleActions[])(PullableLeverEntity*) = {
PullableLever_MiddleInit,
PullableLever_MiddleAction1,
};
const s8 PullableLever_InitialOffsets[] = {
0, 9, -9, 0, 0, -9, 9, 0,
};
void (*const PullableLever_HandleSubActions[])(PullableLeverEntity*) = {
PullableLever_HandleSubAction0,
PullableLever_HandleSubAction1,
};
const s8 gUnk_081222B8[] = {
0, 10, -8, 0, 0, -10, 8, 0,
};
const u8 gUnk_081222C0[] = {
16,
24,
0,
8,
};