mirror of https://github.com/zeldaret/tmc.git
285 lines
8.5 KiB
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,
|
|
};
|